Compare commits

..

2 Commits

17 changed files with 91 additions and 64 deletions

View File

@@ -128,8 +128,8 @@ func testL1RelayerGasOracleConfirm(t *testing.T) {
l1BlockOrm := orm.NewL1Block(db)
l1Block := []orm.L1Block{
{Hash: "gas-oracle-1", Number: 0},
{Hash: "gas-oracle-2", Number: 1},
{Hash: "gas-oracle-1", Number: 0, GasOracleStatus: int(types.GasOraclePending), BlockStatus: int(types.L1BlockPending)},
{Hash: "gas-oracle-2", Number: 1, GasOracleStatus: int(types.GasOraclePending), BlockStatus: int(types.L1BlockPending)},
}
// Insert test data.
assert.NoError(t, l1BlockOrm.InsertL1Blocks(context.Background(), l1Block))

View File

@@ -149,9 +149,11 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error {
baseFee = block.BaseFee.Uint64()
}
blocks = append(blocks, orm.L1Block{
Number: uint64(height),
Hash: block.Hash().String(),
BaseFee: baseFee,
Number: uint64(height),
Hash: block.Hash().String(),
BaseFee: baseFee,
GasOracleStatus: int(types.GasOraclePending),
BlockStatus: int(types.L1BlockPending),
})
}

View File

@@ -33,7 +33,7 @@ type Batch struct {
BatchHeader []byte `json:"batch_header" gorm:"column:batch_header"`
// proof
ChunkProofsStatus int16 `json:"chunk_proofs_status" gorm:"column:chunk_proofs_status"`
ChunkProofsStatus int16 `json:"chunk_proofs_status" gorm:"column:chunk_proofs_status;default:1"`
ProvingStatus int16 `json:"proving_status" gorm:"column:proving_status;default:1"`
Proof []byte `json:"proof" gorm:"column:proof;default:NULL"`
ProverAssignedAt *time.Time `json:"prover_assigned_at" gorm:"column:prover_assigned_at;default:NULL"`
@@ -263,6 +263,7 @@ func (o *Batch) InsertBatch(ctx context.Context, startChunkIndex, endChunkIndex
ChunkProofsStatus: int16(types.ChunkProofsStatusPending),
ProvingStatus: int16(types.ProvingTaskUnassigned),
RollupStatus: int16(types.RollupPending),
OracleStatus: int16(types.GasOraclePending),
}
db := o.db

View File

@@ -63,20 +63,6 @@ func (s GasOracleStatus) String() string {
}
}
// L1BlockInfo is structure of stored l1 block
type L1BlockInfo struct {
Number uint64 `json:"number" db:"number"`
Hash string `json:"hash" db:"hash"`
HeaderRLP string `json:"header_rlp" db:"header_rlp"`
BaseFee uint64 `json:"base_fee" db:"base_fee"`
BlockStatus L1BlockStatus `json:"block_status" db:"block_status"`
GasOracleStatus GasOracleStatus `json:"oracle_status" db:"oracle_status"`
ImportTxHash sql.NullString `json:"import_tx_hash" db:"import_tx_hash"`
OracleTxHash sql.NullString `json:"oracle_tx_hash" db:"oracle_tx_hash"`
}
// MsgStatus represents current layer1 transaction processing status
type MsgStatus int
@@ -145,8 +131,10 @@ type BlockInfo struct {
type RollerProveStatus int32
const (
// RollerProveStatusUndefined indicates an unknown roller proving status
RollerProveStatusUndefined RollerProveStatus = iota
// RollerAssigned indicates roller assigned but has not submitted proof
RollerAssigned RollerProveStatus = iota
RollerAssigned
// RollerProofValid indicates roller has submitted valid proof
RollerProofValid
// RollerProofInvalid indicates roller has submitted invalid proof
@@ -166,11 +154,19 @@ func (s RollerProveStatus) String() string {
}
}
// RollerStatus is the roller name and roller prove status
type RollerStatus struct {
PublicKey string `json:"public_key"`
Name string `json:"name"`
Status RollerProveStatus `json:"status"`
// RollerFailureType is the type of a roller session's failure
type RollerFailureType int
const (
// RollerFailureTypeUndefined indicates an unknown roller failure type
RollerFailureTypeUndefined RollerFailureType = iota
)
func (s RollerFailureType) String() string {
switch s {
default:
return fmt.Sprintf("Undefined (%d)", int32(s))
}
}
// ProvingStatus block_batch proving_status (unassigned, assigned, proved, verified, submitted)

View File

@@ -38,8 +38,10 @@ func (r ProofType) String() string {
}
const (
// ProofTypeUndefined is an unknown proof type
ProofTypeUndefined ProofType = iota
// ProofTypeChunk is default roller, it only generates zk proof from traces.
ProofTypeChunk ProofType = iota
ProofTypeChunk
// ProofTypeBatch generates zk proof from other zk proofs and aggregate them into one proof.
ProofTypeBatch
)

View File

@@ -57,7 +57,7 @@ func TestIdentityHash(t *testing.T) {
hash, err := identity.Hash()
assert.NoError(t, err)
expectedHash := "b3f152958dc881446fc131a250526139d909710c6b91b4d3281ceded28ce2e32"
expectedHash := "063a3620db7f71e5ae99dd622222e1e893247344727fb2a2b022524d06f35aaf"
assert.Equal(t, expectedHash, hex.EncodeToString(hash))
}
@@ -109,15 +109,15 @@ func TestProofDetailHash(t *testing.T) {
}
hash, err := proofDetail.Hash()
assert.NoError(t, err)
expectedHash := "fdfaae752d6fd72a7fdd2ad034ef504d3acda9e691a799323cfa6e371684ba2b"
expectedHash := "8ad894c2047166a98b1a389b716b06b01dc1bd29e950e2687ffbcb3c328edda5"
assert.Equal(t, expectedHash, hex.EncodeToString(hash))
}
func TestProveTypeString(t *testing.T) {
proofTypeChunk := ProofType(0)
proofTypeChunk := ProofType(1)
assert.Equal(t, "proof type chunk", proofTypeChunk.String())
proofTypeBatch := ProofType(1)
proofTypeBatch := ProofType(2)
assert.Equal(t, "proof type batch", proofTypeBatch.String())
illegalProof := ProofType(3)

View File

@@ -5,7 +5,7 @@ import (
"runtime/debug"
)
var tag = "v4.0.12"
var tag = "v4.0.13"
var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {

View File

@@ -97,6 +97,14 @@ contract L1StandardERC20Gateway is Initializable, ScrollGatewayBase, L1ERC20Gate
require(_l2Token != address(0), "token address cannot be 0");
require(getL2ERC20Address(_l1Token) == _l2Token, "l2 token mismatch");
// update `tokenMapping` on first withdraw
address _storedL2Token = tokenMapping[_l1Token];
if (_storedL2Token == address(0)) {
tokenMapping[_l1Token] = _l2Token;
} else {
require(_storedL2Token == _l2Token, "l2 token mismatch");
}
// @note can possible trigger reentrant call to messenger,
// but it seems not a big problem.
IERC20(_l1Token).safeTransfer(_to, _amount);
@@ -126,17 +134,20 @@ contract L1StandardERC20Gateway is Initializable, ScrollGatewayBase, L1ERC20Gate
// 2. Generate message passed to L2StandardERC20Gateway.
address _l2Token = tokenMapping[_token];
bytes memory _l2Data = _data;
bytes memory _l2Data;
if (_l2Token == address(0)) {
// It is a new token, compute and store mapping in storage.
// @note we won't update `tokenMapping` here but update the `tokenMapping` on
// first successful withdraw. This will prevent user to set arbitrary token
// metadata by setting a very small `_gasLimit` on the first tx.
_l2Token = getL2ERC20Address(_token);
tokenMapping[_token] = _l2Token;
// passing symbol/name/decimal in order to deploy in L2.
string memory _symbol = IERC20Metadata(_token).symbol();
string memory _name = IERC20Metadata(_token).name();
uint8 _decimals = IERC20Metadata(_token).decimals();
_l2Data = abi.encode(_data, abi.encode(_symbol, _name, _decimals));
_l2Data = abi.encode(true, abi.encode(_data, abi.encode(_symbol, _name, _decimals)));
} else {
_l2Data = abi.encode(false, _data);
}
bytes memory _message = abi.encodeWithSelector(
IL2ERC20Gateway.finalizeDepositERC20.selector,

View File

@@ -77,7 +77,7 @@ contract L2StandardERC20Gateway is Initializable, ScrollGatewayBase, L2ERC20Gate
address _from,
address _to,
uint256 _amount,
bytes calldata _data
bytes memory _data
) external payable override onlyCallByCounterpart nonReentrant {
require(msg.value == 0, "nonzero msg.value");
require(_l1Token != address(0), "token address cannot be 0");
@@ -91,12 +91,13 @@ contract L2StandardERC20Gateway is Initializable, ScrollGatewayBase, L2ERC20Gate
require(_l2Token == _expectedL2Token, "l2 token mismatch");
}
bool _hasMetadata;
(_hasMetadata, _data) = abi.decode(_data, (bool, bytes));
bytes memory _deployData;
bytes memory _callData;
if (tokenMapping[_l2Token] == address(0)) {
// first deposit, update mapping
tokenMapping[_l2Token] = _l1Token;
if (_hasMetadata) {
(_callData, _deployData) = abi.decode(_data, (bytes, bytes));
} else {
require(tokenMapping[_l2Token] == _l1Token, "token mapping mismatch");
@@ -104,6 +105,9 @@ contract L2StandardERC20Gateway is Initializable, ScrollGatewayBase, L2ERC20Gate
}
if (!_l2Token.isContract()) {
// first deposit, update mapping
tokenMapping[_l2Token] = _l1Token;
_deployL2Token(_deployData, _l1Token);
}

View File

@@ -412,7 +412,7 @@ contract L1StandardERC20GatewayTest is L1GatewayTestBase {
address(this),
address(this),
amount,
abi.encode(new bytes(0), abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals()))
abi.encode(true, abi.encode(new bytes(0), abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals())))
);
bytes memory xDomainCalldata = abi.encodeWithSignature(
"relayMessage(address,address,uint256,uint256,bytes)",
@@ -483,7 +483,7 @@ contract L1StandardERC20GatewayTest is L1GatewayTestBase {
address(this),
recipient,
amount,
abi.encode(new bytes(0), abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals()))
abi.encode(true, abi.encode(new bytes(0), abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals())))
);
bytes memory xDomainCalldata = abi.encodeWithSignature(
"relayMessage(address,address,uint256,uint256,bytes)",
@@ -555,7 +555,7 @@ contract L1StandardERC20GatewayTest is L1GatewayTestBase {
address(this),
recipient,
amount,
abi.encode(dataToCall, abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals()))
abi.encode(true, abi.encode(dataToCall, abi.encode(l1Token.symbol(), l1Token.name(), l1Token.decimals())))
);
bytes memory xDomainCalldata = abi.encodeWithSignature(
"relayMessage(address,address,uint256,uint256,bytes)",

View File

@@ -83,7 +83,7 @@ contract L2StandardERC20GatewayTest is L2GatewayTestBase {
address(this),
address(this),
type(uint128).max,
abi.encode("", abi.encode("symbol", "name", 18))
abi.encode(true, abi.encode("", abi.encode("symbol", "name", 18)))
)
);
hevm.stopPrank();
@@ -285,7 +285,7 @@ contract L2StandardERC20GatewayTest is L2GatewayTestBase {
sender,
address(recipient),
amount,
dataToCall
abi.encode(false, dataToCall)
);
bytes memory xDomainCalldata = abi.encodeWithSignature(
"relayMessage(address,address,uint256,uint256,bytes)",

View File

@@ -33,7 +33,7 @@ type Batch struct {
BatchHeader []byte `json:"batch_header" gorm:"column:batch_header"`
// proof
ChunkProofsStatus int16 `json:"chunk_proofs_status" gorm:"column:chunk_proofs_status"`
ChunkProofsStatus int16 `json:"chunk_proofs_status" gorm:"column:chunk_proofs_status;default:1"`
ProvingStatus int16 `json:"proving_status" gorm:"column:proving_status;default:1"`
Proof []byte `json:"proof" gorm:"column:proof;default:NULL"`
ProverAssignedAt *time.Time `json:"prover_assigned_at" gorm:"column:prover_assigned_at;default:NULL"`
@@ -48,7 +48,7 @@ type Batch struct {
FinalizedAt *time.Time `json:"finalized_at" gorm:"column:finalized_at;default:NULL"`
// gas oracle
OracleStatus int16 `json:"oracle_status" gorm:"column:oracle_status;default:1"`
OracleStatus int16 `json:"oracle_status" gorm:"column:oracle_status;default:1;default:1"`
OracleTxHash string `json:"oracle_tx_hash" gorm:"column:oracle_tx_hash;default:NULL"`
// metadata

View File

@@ -672,6 +672,7 @@ func (m *Manager) StartChunkProofGenerationSession(task *orm.Chunk, prevSession
TaskType: int16(message.ProofTypeChunk),
ProverName: roller.Name,
ProvingStatus: int16(types.RollerAssigned),
FailureType: int16(types.RollerFailureTypeUndefined),
CreatedAt: time.Now(), // Used in proverTasks, should be explicitly assigned here.
}
// Store prover task info.
@@ -771,6 +772,7 @@ func (m *Manager) StartBatchProofGenerationSession(task *orm.Batch, prevSession
TaskType: int16(message.ProofTypeBatch),
ProverName: roller.Name,
ProvingStatus: int16(types.RollerAssigned),
FailureType: int16(types.RollerFailureTypeUndefined),
CreatedAt: time.Now(), // Used in proverTasks, should be explicitly assigned here.
}
// Store session info.

View File

@@ -2,19 +2,19 @@
-- +goose StatementBegin
create table l1_message
(
queue_index BIGINT NOT NULL,
msg_hash VARCHAR NOT NULL,
height BIGINT NOT NULL,
gas_limit BIGINT NOT NULL,
sender VARCHAR NOT NULL,
target VARCHAR NOT NULL,
value VARCHAR NOT NULL,
calldata TEXT NOT NULL,
layer1_hash VARCHAR NOT NULL,
layer2_hash VARCHAR DEFAULT NULL,
status INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP
queue_index BIGINT NOT NULL,
msg_hash VARCHAR NOT NULL,
height BIGINT NOT NULL,
gas_limit BIGINT NOT NULL,
sender VARCHAR NOT NULL,
target VARCHAR NOT NULL,
value VARCHAR NOT NULL,
calldata TEXT NOT NULL,
layer1_hash VARCHAR NOT NULL,
layer2_hash VARCHAR DEFAULT NULL,
status INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
comment

View File

@@ -7,9 +7,9 @@ create table l1_block
hash VARCHAR NOT NULL,
header_rlp TEXT NOT NULL,
base_fee BIGINT NOT NULL,
block_status INTEGER DEFAULT 1,
block_status INTEGER NOT NULL DEFAULT 1,
import_tx_hash VARCHAR DEFAULT NULL,
oracle_status INTEGER DEFAULT 1,
oracle_status INTEGER NOT NULL DEFAULT 1,
oracle_tx_hash VARCHAR DEFAULT NULL
);

View File

@@ -15,7 +15,7 @@ create table batch
batch_header BYTEA NOT NULL,
-- proof
chunk_proofs_status SMALLINT NOT NULL,
chunk_proofs_status SMALLINT NOT NULL DEFAULT 1,
proving_status SMALLINT NOT NULL DEFAULT 1,
proof BYTEA DEFAULT NULL,
prover_assigned_at TIMESTAMP(0) DEFAULT NULL,
@@ -45,6 +45,9 @@ on batch (index);
create unique index batch_hash_uindex
on batch (hash);
comment
on column batch.chunk_proofs_status is 'undefined, pending, ready';
comment
on column batch.proving_status is 'undefined, unassigned, skipped, assigned, proved, verified, failed';

View File

@@ -20,7 +20,13 @@ create table prover_task
);
comment
on column batch.proving_status is 'roller assigned, roller proof valid, roller proof invalid';
on column prover_task.task_type is 'undefined, chunk, batch';
comment
on column prover_task.proving_status is 'undefined, roller assigned, roller proof valid, roller proof invalid';
comment
on column prover_task.failure_type is 'undefined';
-- +goose StatementEnd