diff --git a/packages/protocol/contracts/L1/TaikoErrors.sol b/packages/protocol/contracts/L1/TaikoErrors.sol index 62eb158da66..70ff4ca0936 100644 --- a/packages/protocol/contracts/L1/TaikoErrors.sol +++ b/packages/protocol/contracts/L1/TaikoErrors.sol @@ -29,6 +29,7 @@ abstract contract TaikoErrors { error L1_NOT_ASSIGNED_PROVER(); error L1_PROVING_PAUSED(); error L1_RECEIVE_DISABLED(); + error L1_TOO_LATE(); error L1_TOO_MANY_BLOCKS(); error L1_TRANSITION_ID_ZERO(); error L1_TRANSITION_NOT_FOUND(); diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index bfa78a7baf2..d5074c2c428 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -66,6 +66,10 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents, TaikoErrors { state.__reserve1 = 0; } + function resetGenesisHash(bytes32 _genesisBlockHash) external onlyOwner { + LibVerifying.resetGenesisHash(state, _genesisBlockHash); + } + /// @inheritdoc ITaikoL1 function proposeBlock( bytes calldata _params, diff --git a/packages/protocol/contracts/L1/libs/LibVerifying.sol b/packages/protocol/contracts/L1/libs/LibVerifying.sol index 160b064abf6..1f6f2e557db 100644 --- a/packages/protocol/contracts/L1/libs/LibVerifying.sol +++ b/packages/protocol/contracts/L1/libs/LibVerifying.sol @@ -41,6 +41,7 @@ library LibVerifying { error L1_INVALID_CONFIG(); error L1_INVALID_GENESIS_HASH(); error L1_TRANSITION_ID_ZERO(); + error L1_TOO_LATE(); /// @notice Initializes the Taiko protocol state. /// @param _state The state to initialize. @@ -54,33 +55,14 @@ library LibVerifying { internal { if (!_isConfigValid(_config)) revert L1_INVALID_CONFIG(); - if (_genesisBlockHash == 0) revert L1_INVALID_GENESIS_HASH(); - // Init state - _state.slotA.genesisHeight = uint64(block.number); - _state.slotA.genesisTimestamp = uint64(block.timestamp); - _state.slotB.numBlocks = 1; + _setupGenesisBlock(_state, _genesisBlockHash); + } - // Init the genesis block - TaikoData.Block storage blk = _state.blocks[0]; - blk.nextTransitionId = 2; - blk.proposedAt = uint64(block.timestamp); - blk.verifiedTransitionId = 1; - blk.metaHash = bytes32(uint256(1)); // Give the genesis metahash a non-zero value. + function resetGenesisHash(TaikoData.State storage _state, bytes32 _genesisBlockHash) internal { + if (_state.slotB.numBlocks != 1) revert L1_TOO_LATE(); - // Init the first state transition - TaikoData.TransitionState storage ts = _state.transitions[0][1]; - ts.blockHash = _genesisBlockHash; - ts.prover = address(0); - ts.timestamp = uint64(block.timestamp); - - emit BlockVerified({ - blockId: 0, - prover: address(0), - blockHash: _genesisBlockHash, - stateRoot: 0, - tier: 0 - }); + _setupGenesisBlock(_state, _genesisBlockHash); } /// @dev Verifies up to N blocks. @@ -211,6 +193,40 @@ library LibVerifying { emit StateVariablesUpdated({ slotB: _state.slotB }); } + function _setupGenesisBlock( + TaikoData.State storage _state, + bytes32 _genesisBlockHash + ) + private + { + if (_genesisBlockHash == 0) revert L1_INVALID_GENESIS_HASH(); + // Init state + _state.slotA.genesisHeight = uint64(block.number); + _state.slotA.genesisTimestamp = uint64(block.timestamp); + _state.slotB.numBlocks = 1; + + // Init the genesis block + TaikoData.Block storage blk = _state.blocks[0]; + blk.nextTransitionId = 2; + blk.proposedAt = uint64(block.timestamp); + blk.verifiedTransitionId = 1; + blk.metaHash = bytes32(uint256(1)); // Give the genesis metahash a non-zero value. + + // Init the first state transition + TaikoData.TransitionState storage ts = _state.transitions[0][1]; + ts.blockHash = _genesisBlockHash; + ts.prover = address(0); + ts.timestamp = uint64(block.timestamp); + + emit BlockVerified({ + blockId: 0, + prover: address(0), + blockHash: _genesisBlockHash, + stateRoot: 0, + tier: 0 + }); + } + function _syncChainData( TaikoData.State storage _state, TaikoData.Config memory _config,