Skip to content

Commit

Permalink
feat(protocol): apply multiple improvements for "ontake" fork (#17734)
Browse files Browse the repository at this point in the history
Co-authored-by: David <david@taiko.xyz>
Co-authored-by: maskpp <maskpp266@gmail.com>
  • Loading branch information
3 people committed Jul 24, 2024
1 parent d538d99 commit 17d67d7
Show file tree
Hide file tree
Showing 33 changed files with 1,199 additions and 311 deletions.
11 changes: 11 additions & 0 deletions packages/protocol/contracts/L1/ITaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ interface ITaikoL1 {
payable
returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_);

/// @notice Proposes a Taiko L2 block (version 2)
/// @param _params Block parameters, currently an encoded BlockParams object.
/// @param _txList txList data if calldata is used for DA.
/// @return meta_ The metadata of the proposed L2 block.
function proposeBlockV2(
bytes calldata _params,
bytes calldata _txList
)
external
returns (TaikoData.BlockMetadataV2 memory meta_);

/// @notice Proves or contests a block transition.
/// @param _blockId The index of the block to prove. This is also used to
/// select the right implementation version.
Expand Down
69 changes: 62 additions & 7 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,17 @@ library TaikoData {
// ---------------------------------------------------------------------
// The number of L2 blocks between each L2-to-L1 state root sync.
uint8 stateRootSyncInternal;
bool checkEOAForCalldataDA;
uint64 maxAnchorHeightOffset;
// ---------------------------------------------------------------------
// Group 5: Previous configs in TaikoL2
// ---------------------------------------------------------------------
uint8 basefeeAdjustmentQuotient;
uint8 basefeeSharingPctg;
uint32 blockGasIssuance;
// ---------------------------------------------------------------------
// Group 6: Others
// ---------------------------------------------------------------------
uint64 ontakeForkHeight;
}

/// @dev A proof and the tier of proof it belongs to
Expand All @@ -57,7 +67,18 @@ library TaikoData {
bytes32 extraData;
bytes32 parentMetaHash;
HookCall[] hookCalls; // DEPRECATED, value ignored.
bytes signature;
bytes signature; // DEPRECATED, value ignored.
}

struct BlockParamsV2 {
address coinbase;
bytes32 extraData;
bytes32 parentMetaHash;
uint64 anchorBlockId; // NEW
uint64 timestamp; // NEW
uint32 blobTxListOffset; // NEW
uint32 blobTxListLength; // NEW
uint8 blobIndex; // NEW
}

/// @dev Struct containing data only required for proving a block
Expand All @@ -81,6 +102,33 @@ library TaikoData {
address sender; // a.k.a proposer
}

struct BlockMetadataV2 {
bytes32 anchorBlockHash; // `_l1BlockHash` in TaikoL2's anchor tx.
bytes32 difficulty;
bytes32 blobHash;
bytes32 extraData;
address coinbase;
uint64 id;
uint32 gasLimit;
uint64 timestamp;
uint64 anchorBlockId; // `_l1BlockId` in TaikoL2's anchor tx.
uint16 minTier;
bool blobUsed;
bytes32 parentMetaHash;
address proposer;
uint96 livenessBond;
// Time this block is proposed at, used to check proving window and cooldown window.
uint64 proposedAt;
// L1 block number, required/used by node/client.
uint64 proposedIn;
uint32 blobTxListOffset;
uint32 blobTxListLength;
uint8 blobIndex;
uint8 basefeeAdjustmentQuotient;
uint8 basefeeSharingPctg;
uint32 blockGasIssuance;
}

/// @dev Struct representing transition to be proven.
struct Transition {
bytes32 parentHash;
Expand Down Expand Up @@ -111,13 +159,20 @@ library TaikoData {
address assignedProver; // slot 2
uint96 livenessBond;
uint64 blockId; // slot 3
uint64 proposedAt; // timestamp
uint64 proposedIn; // L1 block number, required/used by node/client.
uint32 nextTransitionId;
// Before the fork, this field is the L1 timestamp when this block is proposed.
// After the fork, this is the timestamp of the L2 block.
// In a later fork, we an rename this field to `timestamp`.
uint64 proposedAt;
// Before the fork, this field is the L1 block number where this block is proposed.
// After the fork, this is the L1 block number input for the anchor transaction.
// In a later fork, we an rename this field to `anchorBlockId`.
uint64 proposedIn;
uint24 nextTransitionId;
bool livenessBondReturned;
// The ID of the transaction that is used to verify this block. However, if
// this block is not verified as the last block in a batch, verifiedTransitionId
// will remain zero.
uint32 verifiedTransitionId;
uint24 verifiedTransitionId;
}

/// @dev Struct representing an Ethereum deposit.
Expand Down Expand Up @@ -156,7 +211,7 @@ library TaikoData {
// Ring buffer for proposed blocks and a some recent verified blocks.
mapping(uint64 blockId_mod_blockRingBufferSize => Block blk) blocks;
// Indexing to transition ids (ring buffer not possible)
mapping(uint64 blockId => mapping(bytes32 parentHash => uint32 transitionId)) transitionIds;
mapping(uint64 blockId => mapping(bytes32 parentHash => uint24 transitionId)) transitionIds;
// Ring buffer for transitions
mapping(
uint64 blockId_mod_blockRingBufferSize
Expand Down
47 changes: 47 additions & 0 deletions packages/protocol/contracts/L1/TaikoEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ abstract contract TaikoEvents {
TaikoData.EthDeposit[] depositsProcessed
);

/// @notice Emitted when a block is proposed.
/// @param blockId The ID of the proposed block.
/// @param meta The metadata of the proposed block.
event BlockProposedV2(uint256 indexed blockId, TaikoData.BlockMetadataV2 meta);

/// @notice Emitted when a block's txList is in the calldata.
/// @param blockId The ID of the proposed block.
/// @param txList The txList.
Expand All @@ -51,6 +56,22 @@ abstract contract TaikoEvents {
uint16 tier
);

/// @notice Emitted when a transition is proved.
/// @param blockId The block ID.
/// @param tran The transition data.
/// @param prover The prover's address.
/// @param validityBond The validity bond amount.
/// @param tier The tier of the proof.
/// @param proposedIn The L1 block in which a transition is proved.
event TransitionProvedV2(
uint256 indexed blockId,
TaikoData.Transition tran,
address prover,
uint96 validityBond,
uint16 tier,
uint64 proposedIn
);

/// @notice Emitted when a transition is contested.
/// @param blockId The block ID.
/// @param tran The transition data.
Expand All @@ -65,6 +86,22 @@ abstract contract TaikoEvents {
uint16 tier
);

/// @notice Emitted when a transition is contested.
/// @param blockId The block ID.
/// @param tran The transition data.
/// @param contester The contester's address.
/// @param contestBond The contest bond amount.
/// @param tier The tier of the proof.
/// @param proposedIn The L1 block in which this L2 block is proposed.
event TransitionContestedV2(
uint256 indexed blockId,
TaikoData.Transition tran,
address contester,
uint96 contestBond,
uint16 tier,
uint64 proposedIn
);

/// @notice Emitted when proving is paused or unpaused.
/// @param paused The pause status.
event ProvingPaused(bool paused);
Expand All @@ -84,6 +121,16 @@ abstract contract TaikoEvents {
uint16 tier
);

/// @dev Emitted when a block is verified.
/// @param blockId The ID of the verified block.
/// @param prover The prover whose transition is used for verifying the
/// block.
/// @param blockHash The hash of the verified block.
/// @param tier The tier ID of the proof.
event BlockVerifiedV2(
uint256 indexed blockId, address indexed prover, bytes32 blockHash, uint16 tier
);

/// @notice Emitted when some state variable values changed.
/// @dev This event is currently used by Taiko node/client for block proposal/proving.
/// @param slotB The SlotB data structure.
Expand Down
43 changes: 34 additions & 9 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.24;

import "../common/EssentialContract.sol";
import "./libs/LibData.sol";
import "./libs/LibProposing.sol";
import "./libs/LibProving.sol";
import "./libs/LibVerifying.sol";
Expand All @@ -23,6 +24,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {

uint256[50] private __gap;

error L1_FORK_ERROR();
error L1_RECEIVE_DISABLED();

modifier whenProvingNotPaused() {
Expand Down Expand Up @@ -55,7 +57,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
initializer
{
__Essential_init(_owner, _rollupAddressManager);
LibUtils.init(state, _genesisBlockHash);
LibUtils.init(state, getConfig(), _genesisBlockHash);
if (_toPause) _pause();
}

Expand All @@ -81,7 +83,31 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
{
TaikoData.Config memory config = getConfig();

(meta_, deposits_) = LibProposing.proposeBlock(state, config, this, _params, _txList);
TaikoData.BlockMetadataV2 memory meta2;
(meta2, deposits_) = LibProposing.proposeBlock(state, config, this, _params, _txList);

if (meta2.id >= config.ontakeForkHeight) revert L1_FORK_ERROR();

if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) {
LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify);
}
meta_ = LibData.blockMetadataV2toV1(meta2);
}

function proposeBlockV2(
bytes calldata _params,
bytes calldata _txList
)
external
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadataV2 memory meta_)
{
TaikoData.Config memory config = getConfig();

(meta_,) = LibProposing.proposeBlock(state, config, this, _params, _txList);
if (meta_.id < config.ontakeForkHeight) revert L1_FORK_ERROR();

if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) {
LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify);
Expand Down Expand Up @@ -242,16 +268,15 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
// their data.
blockRingBufferSize: 360_000, // = 7200 * 50
maxBlocksToVerify: 16,
// This value is set based on `gasTargetPerL1Block = 15_000_000 * 4` in TaikoL2.
// We use 8x rather than 4x here to handle the scenario where the average number of
// Taiko blocks proposed per Ethereum block is smaller than 1.
// There is 250_000 additional gas for the anchor tx. Therefore, on explorers, you'll
// read Taiko's gas limit to be 240_250_000.
blockMaxGasLimit: 240_000_000,
livenessBond: 125e18, // 125 Taiko token
stateRootSyncInternal: 16,
checkEOAForCalldataDA: true
});
maxAnchorHeightOffset: 64,
basefeeAdjustmentQuotient: 8,
basefeeSharingPctg: 75,
blockGasIssuance: 20_000_000,
ontakeForkHeight: 374_400 // = 7200 * 52
});
}

/// @dev chain_pauser is supposed to be a cold wallet.
Expand Down
13 changes: 13 additions & 0 deletions packages/protocol/contracts/L1/access/IProposerAccess.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/// @title IProposerAccess
/// @dev An interface to check if a proposer is eligible to propose blocks in a specific Ethereum
/// block.
/// @custom:security-contact security@taiko.xyz
interface IProposerAccess {
/// @notice Checks if a proposer can propose block in the current Ethereum block.
/// @param _proposer The proposer.
/// @return true if the proposer can propose blocks, false otherwise.
function isProposerEligible(address _proposer) external view returns (bool);
}
100 changes: 100 additions & 0 deletions packages/protocol/contracts/L1/libs/LibData.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "../TaikoData.sol";

/// @title LibData
/// @notice A library that offers helper functions.
/// @custom:security-contact security@taiko.xyz
library LibData {
// = keccak256(abi.encode(new TaikoData.EthDeposit[](0)))
bytes32 internal constant EMPTY_ETH_DEPOSIT_HASH =
0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd;

function blockParamsV1ToV2(TaikoData.BlockParams memory _v1)
internal
pure
returns (TaikoData.BlockParamsV2 memory)
{
return TaikoData.BlockParamsV2({
coinbase: _v1.coinbase,
extraData: _v1.extraData,
parentMetaHash: _v1.parentMetaHash,
anchorBlockId: 0,
timestamp: 0,
blobTxListOffset: 0,
blobTxListLength: 0,
blobIndex: 0
});
}

function blockMetadataV2toV1(TaikoData.BlockMetadataV2 memory _v2)
internal
pure
returns (TaikoData.BlockMetadata memory)
{
return TaikoData.BlockMetadata({
l1Hash: _v2.anchorBlockHash,
difficulty: _v2.difficulty,
blobHash: _v2.blobHash,
extraData: _v2.extraData,
depositsHash: EMPTY_ETH_DEPOSIT_HASH,
coinbase: _v2.coinbase,
id: _v2.id,
gasLimit: _v2.gasLimit,
timestamp: _v2.timestamp,
l1Height: _v2.anchorBlockId,
minTier: _v2.minTier,
blobUsed: _v2.blobUsed,
parentMetaHash: _v2.parentMetaHash,
sender: _v2.proposer
});
}

function metadataV1toV2(
TaikoData.BlockMetadata memory _v1,
uint96 _livenessBond
)
internal
pure
returns (TaikoData.BlockMetadataV2 memory)
{
return TaikoData.BlockMetadataV2({
anchorBlockHash: _v1.l1Hash,
difficulty: _v1.difficulty,
blobHash: _v1.blobHash,
extraData: _v1.extraData,
coinbase: _v1.coinbase,
id: _v1.id,
gasLimit: _v1.gasLimit,
timestamp: _v1.timestamp,
anchorBlockId: _v1.l1Height,
minTier: _v1.minTier,
blobUsed: _v1.blobUsed,
parentMetaHash: _v1.parentMetaHash,
proposer: _v1.sender,
livenessBond: _livenessBond,
proposedAt: 0,
proposedIn: 0,
blobTxListOffset: 0,
blobTxListLength: 0,
blobIndex: 0,
basefeeAdjustmentQuotient: 0,
basefeeSharingPctg: 0,
blockGasIssuance: 0
});
}

function hashMetadata(
bool postFork,
TaikoData.BlockMetadataV2 memory _meta
)
internal
pure
returns (bytes32)
{
return postFork
? keccak256(abi.encode(_meta)) //
: keccak256(abi.encode(blockMetadataV2toV1(_meta)));
}
}
Loading

0 comments on commit 17d67d7

Please sign in to comment.