Skip to content

Commit

Permalink
refactor(protocol): reduce gas usage (#18499)
Browse files Browse the repository at this point in the history
  • Loading branch information
dantaik authored Nov 20, 2024
1 parent c04b1c7 commit baf6cfa
Show file tree
Hide file tree
Showing 9 changed files with 16,255 additions and 12,701 deletions.
83 changes: 48 additions & 35 deletions packages/protocol/contracts/layer1/based/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ library LibProposing {
uint256 internal constant SECONDS_PER_BLOCK = 12;

struct Local {
TaikoData.SlotB b;
TaikoData.BlockParamsV2 params;
ITierProvider tierProvider;
bytes32 parentMetaHash;
Expand Down Expand Up @@ -67,12 +66,14 @@ library LibProposing {
}

metas_ = new TaikoData.BlockMetadataV2[](_paramsArr.length);
TaikoData.SlotB memory slotB;

for (uint256 i; i < _paramsArr.length; ++i) {
metas_[i] = _proposeBlock(_state, _config, _resolver, _paramsArr[i], _txListArr[i]);
(metas_[i], slotB) =
_proposeBlock(_state, _config, _resolver, _paramsArr[i], _txListArr[i]);
}

if (!_state.slotB.provingPaused) {
if (!slotB.provingPaused) {
for (uint256 i; i < _paramsArr.length; ++i) {
if (LibUtils.shouldVerifyBlocks(_config, metas_[i].id, false)) {
LibVerifying.verifyBlocks(_state, _config, _resolver, _config.maxBlocksToVerify);
Expand All @@ -98,9 +99,10 @@ library LibProposing {
internal
returns (TaikoData.BlockMetadataV2 memory meta_)
{
meta_ = _proposeBlock(_state, _config, _resolver, _params, _txList);
TaikoData.SlotB memory slotB;
(meta_, slotB) = _proposeBlock(_state, _config, _resolver, _params, _txList);

if (!_state.slotB.provingPaused) {
if (!slotB.provingPaused) {
if (LibUtils.shouldVerifyBlocks(_config, meta_.id, false)) {
LibVerifying.verifyBlocks(_state, _config, _resolver, _config.maxBlocksToVerify);
}
Expand All @@ -122,25 +124,28 @@ library LibProposing {
bytes calldata _txList
)
private
returns (TaikoData.BlockMetadataV2 memory meta_)
returns (TaikoData.BlockMetadataV2 memory meta_, TaikoData.SlotB memory slotB)
{
// Checks proposer access.
Local memory local;
local.b = _state.slotB;
// SLOAD #1 {{
slotB = _state.slotB;
// SLOAD #1 }}

// It's essential to ensure that the ring buffer for proposed blocks still has space for at
// least one more block.
require(local.b.numBlocks >= _config.ontakeForkHeight, L1_FORK_HEIGHT_ERROR());
require(slotB.numBlocks >= _config.ontakeForkHeight, L1_FORK_HEIGHT_ERROR());

unchecked {
require(
local.b.numBlocks < local.b.lastVerifiedBlockId + _config.blockMaxProposals + 1,
slotB.numBlocks < slotB.lastVerifiedBlockId + _config.blockMaxProposals + 1,
L1_TOO_MANY_BLOCKS()
);
}

address preconfTaskManager =
_resolver.resolve(block.chainid, LibStrings.B_PRECONF_TASK_MANAGER, true);

Local memory local;

if (preconfTaskManager != address(0)) {
require(preconfTaskManager == msg.sender, L1_INVALID_PROPOSER());
local.allowCustomProposer = true;
Expand All @@ -150,22 +155,22 @@ library LibProposing {
local.params = abi.decode(_params, (TaikoData.BlockParamsV2));
}

_validateParams(_state, _config, local);
_validateParams(_state, _config, slotB, local);

// Initialize metadata to compute a metaHash, which forms a part of the block data to be
// stored on-chain for future integrity checks. If we choose to persist all data fields in
// the metadata, it will require additional storage slots.
meta_ = TaikoData.BlockMetadataV2({
anchorBlockHash: blockhash(local.params.anchorBlockId),
difficulty: keccak256(abi.encode("TAIKO_DIFFICULTY", local.b.numBlocks)),
difficulty: keccak256(abi.encode("TAIKO_DIFFICULTY", slotB.numBlocks)),
blobHash: 0, // to be initialized below
// Encode _config.baseFeeConfig into extraData to allow L2 block execution without
// metadata. Metadata might be unavailable until the block is proposed on-chain. In
// preconfirmation scenarios, multiple blocks may be built but not yet proposed, making
// metadata unavailable.
extraData: _encodeBaseFeeConfig(_config.baseFeeConfig),
extraData: _encodeBaseFeeConfig(_config.baseFeeConfig), // TODO(daniel):remove outside and compute only once.
coinbase: local.params.coinbase,
id: local.b.numBlocks,
id: slotB.numBlocks,
gasLimit: _config.blockMaxGasLimit,
timestamp: local.params.timestamp,
anchorBlockId: local.params.anchorBlockId,
Expand Down Expand Up @@ -197,44 +202,52 @@ library LibProposing {

// Use the difficulty as a random number
meta_.minTier = local.tierProvider.getMinTier(
local.b.numBlocks, meta_.proposer, uint256(meta_.difficulty)
slotB.numBlocks, meta_.proposer, uint256(meta_.difficulty)
);

// Create the block that will be stored onchain
TaikoData.BlockV2 memory blk = TaikoData.BlockV2({
metaHash: keccak256(abi.encode(meta_)),
assignedProver: address(0),
livenessBond: 0,
blockId: local.b.numBlocks,
proposedAt: local.params.timestamp, // = params.timestamp post Ontake
proposedIn: local.params.anchorBlockId, // = params.anchorBlockId post Ontake
nextTransitionId: 1, // For a new block, the next transition ID is always 1, not 0.
livenessBondReturned: false,
// For unverified block, its verifiedTransitionId is always 0.
verifiedTransitionId: 0
});
// Use a storage pointer for the block in the ring buffer
TaikoData.BlockV2 storage blk = _state.blocks[slotB.numBlocks % _config.blockRingBufferSize];

// Store the block in the ring buffer
_state.blocks[local.b.numBlocks % _config.blockRingBufferSize] = blk;
// Store each field of the block separately
// SSTORE #1 {{
blk.metaHash = keccak256(abi.encode(meta_));
// SSTORE #1 }}

// SSTORE #2 {{
blk.blockId = slotB.numBlocks;
blk.proposedAt = local.params.timestamp;
blk.proposedIn = local.params.anchorBlockId;
blk.nextTransitionId = 1;
blk.livenessBondReturned = false;
blk.verifiedTransitionId = 0;
// SSTORE #2 }}

// Increment the counter (cursor) by 1.
unchecked {
++_state.slotB.numBlocks;
// Increment the counter (cursor) by 1.
slotB.numBlocks += 1;
slotB.lastProposedIn = uint56(block.number);

// SSTORE #3 {{
_state.slotB = slotB; // TODO(daniel): save this only once.
// SSTORE #3 }}
}
_state.slotB.lastProposedIn = uint56(block.number);

// SSTORE #4 {{
LibBonds.debitBond(_state, _resolver, local.params.proposer, meta_.id, _config.livenessBond);
// SSTORE #4 }}

emit BlockProposedV2(meta_.id, meta_);
}

/// @dev Validates the parameters for proposing a block.
/// @param _state Pointer to the protocol's storage.
/// @param _config The configuration parameters for the Taiko protocol.
/// @param _slotB The SlotB struct.
/// @param _local The local struct.
function _validateParams(
TaikoData.State storage _state,
TaikoData.Config memory _config,
TaikoData.SlotB memory _slotB,
Local memory _local
)
private
Expand Down Expand Up @@ -266,7 +279,7 @@ library LibProposing {
// Verify params against the parent block.
TaikoData.BlockV2 storage parentBlk;
unchecked {
parentBlk = _state.blocks[(_local.b.numBlocks - 1) % _config.blockRingBufferSize];
parentBlk = _state.blocks[(_slotB.numBlocks - 1) % _config.blockRingBufferSize];
}

// Verify the passed in L1 state block number to anchor.
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"ds-test": "github:dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0",
"eigenlayer-contracts": "github:Layr-labs/eigenlayer-contracts#dev",
"eigenlayer-middleware": "github:layr-Labs/eigenlayer-middleware#mainnet",
"forge-std": "github:foundry-rs/forge-std#v1.7.5",
"forge-std": "github:foundry-rs/forge-std#v1.9.4",
"merkletreejs": "^0.4.0",
"optimism": "github:ethereum-optimism/optimism#v1.8.0",
"p256-verifier": "github:taikoxyz/p256-verifier#v0.1.0",
Expand Down
61 changes: 61 additions & 0 deletions packages/protocol/snapshots/gasUsed_proposeBlock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"100001": "169357",
"100002": "88742",
"100003": "88772",
"100004": "96058",
"100005": "88832",
"100006": "88861",
"100007": "88890",
"100008": "88920",
"100009": "88949",
"100010": "88979",
"100011": "89009",
"100012": "96294",
"100013": "89068",
"100014": "89098",
"100015": "89127",
"100016": "89156",
"100017": "89186",
"100018": "89216",
"100019": "89245",
"100020": "96530",
"100021": "89303",
"100022": "89333",
"100023": "89363",
"100024": "89393",
"100025": "53222",
"100026": "45551",
"100027": "45581",
"100028": "50867",
"100029": "45641",
"100030": "45670",
"100031": "45699",
"100032": "45729",
"100033": "45758",
"100034": "45788",
"100035": "45817",
"100036": "51103",
"100037": "45876",
"100038": "45906",
"100039": "45935",
"100040": "45965",
"100041": "45995",
"100042": "46024",
"100043": "46054",
"100044": "51339",
"100045": "46113",
"100046": "46142",
"100047": "46172",
"100048": "46201",
"100049": "46231",
"100050": "46261",
"100051": "46290",
"100052": "51575",
"100053": "46349",
"100054": "46378",
"100055": "46408",
"100056": "46437",
"100057": "46467",
"100058": "46496",
"100059": "46526"
}
61 changes: 61 additions & 0 deletions packages/protocol/snapshots/gasUsed_proveBlock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"100001": "183075",
"100002": "143652",
"100003": "163601",
"100004": "139734",
"100005": "163683",
"100006": "143819",
"100007": "163767",
"100008": "151612",
"100009": "163850",
"100010": "143985",
"100011": "163934",
"100012": "140068",
"100013": "164016",
"100014": "144151",
"100015": "164100",
"100016": "151945",
"100017": "164183",
"100018": "144318",
"100019": "164267",
"100020": "140402",
"100021": "164351",
"100022": "144485",
"100023": "164433",
"100024": "152278",
"100025": "128217",
"100026": "52852",
"100027": "72800",
"100028": "50934",
"100029": "72883",
"100030": "53018",
"100031": "72967",
"100032": "60811",
"100033": "73050",
"100034": "53185",
"100035": "73134",
"100036": "51268",
"100037": "73217",
"100038": "53351",
"100039": "73301",
"100040": "61144",
"100041": "73383",
"100042": "53518",
"100043": "73467",
"100044": "51601",
"100045": "73550",
"100046": "53684",
"100047": "73634",
"100048": "61478",
"100049": "73716",
"100050": "53851",
"100051": "73800",
"100052": "51935",
"100053": "73883",
"100054": "54018",
"100055": "73967",
"100056": "61812",
"100057": "74050",
"100058": "54185",
"100059": "74133"
}
61 changes: 61 additions & 0 deletions packages/protocol/snapshots/gasUsed_verifyBlocks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"100001": "117578",
"100002": "44054",
"100003": "75878",
"100004": "44054",
"100005": "75878",
"100006": "44054",
"100007": "75878",
"100008": "44054",
"100009": "75878",
"100010": "44054",
"100011": "75878",
"100012": "44054",
"100013": "75878",
"100014": "44054",
"100015": "75878",
"100016": "44054",
"100017": "75878",
"100018": "44054",
"100019": "75878",
"100020": "44054",
"100021": "75878",
"100022": "44054",
"100023": "75878",
"100024": "44054",
"100025": "75878",
"100026": "44054",
"100027": "75878",
"100028": "44054",
"100029": "75878",
"100030": "44054",
"100031": "75878",
"100032": "44054",
"100033": "75878",
"100034": "44054",
"100035": "75878",
"100036": "44054",
"100037": "75878",
"100038": "44054",
"100039": "75878",
"100040": "44054",
"100041": "75878",
"100042": "44054",
"100043": "75878",
"100044": "44054",
"100045": "75878",
"100046": "44054",
"100047": "75878",
"100048": "44054",
"100049": "75878",
"100050": "44054",
"100051": "75878",
"100052": "44054",
"100053": "75878",
"100054": "44054",
"100055": "75878",
"100056": "44054",
"100057": "75878",
"100058": "44054",
"100059": "75878"
}
Loading

0 comments on commit baf6cfa

Please sign in to comment.