Skip to content

Commit

Permalink
refactor: pad when needed and not sooner (#5482)
Browse files Browse the repository at this point in the history
Fixes #5357
  • Loading branch information
benesjan committed Apr 3, 2024
1 parent 02524e1 commit e928c33
Show file tree
Hide file tree
Showing 32 changed files with 394 additions and 336 deletions.
48 changes: 38 additions & 10 deletions l1-contracts/src/core/libraries/decoders/TxsDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Hash} from "../Hash.sol";
* @dev Assumes the input trees to be padded.
*
* -------------------
* You can use scripts/l2_block_data_specification_comment.py to generate the below outline.
* You can use scripts/l2_block_data_specification_comment.py to generate the below outline. --> SCRIPT STALE NOW!
* -------------------
* L2 Body Data Specification
* -------------------
Expand Down Expand Up @@ -68,25 +68,25 @@ library TxsDecoder {
}

/**
* @notice Computes consumables for the block
* @param _body - The L2 block calldata.
* @return diffRoot - The root of the diff tree (new note hashes, nullifiers etc)
* @notice Computes txs effects hash
* @param _body - The L2 block body calldata.
* @return The txs effects hash.
*/
function decode(bytes calldata _body) internal pure returns (bytes32) {
ArrayOffsets memory offsets;
Counts memory counts;
ConsumablesVars memory vars;
uint256 offset = 0;

{
uint256 count = read4(_body, offset); // number of tx effects
offset += 0x4;
vars.baseLeaves = new bytes32[](count);
}
uint32 numTxEffects = uint32(read4(_body, offset));
uint256 numTxEffectsToPad = computeNumTxEffectsToPad(numTxEffects);

offset += 0x4;
vars.baseLeaves = new bytes32[](numTxEffects + numTxEffectsToPad);

// Data starts after header. Look at L2 Block Data specification at the top of this file.
{
for (uint256 i = 0; i < vars.baseLeaves.length; i++) {
for (uint256 i = 0; i < numTxEffects; i++) {
/*
* Compute the leaf to insert.
* Leaf_i = (
Expand Down Expand Up @@ -179,6 +179,12 @@ library TxsDecoder {

vars.baseLeaves[i] = Hash.sha256ToField(vars.baseLeaf);
}

// We pad base leaves with hashes of empty tx effect.
for (uint256 i = numTxEffects; i < vars.baseLeaves.length; i++) {
// Value taken from tx_effect.test.ts "hash of empty tx effect matches snapshot" test case
vars.baseLeaves[i] = hex"0071f7630d28ce02cc1ca8b15c44953f84a39e1478445395247ae04dfa213c0e";
}
}

return computeRoot(vars.baseLeaves);
Expand Down Expand Up @@ -344,4 +350,26 @@ library TxsDecoder {
function read4(bytes calldata _data, uint256 _offset) internal pure returns (uint256) {
return uint256(uint32(bytes4(slice(_data, _offset, 4))));
}

function computeNumTxEffectsToPad(uint32 _numTxEffects) internal pure returns (uint32) {
// 2 is the minimum number of tx effects so we have to handle the following 2 cases separately
if (_numTxEffects == 0) {
return 2;
} else if (_numTxEffects == 1) {
return 1;
}

uint32 v = _numTxEffects;

// the following rounds _numTxEffects up to the next power of 2 (works only for 4 bytes value!)
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;

return v - _numTxEffects;
}
}
22 changes: 17 additions & 5 deletions l1-contracts/test/Rollup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity >=0.8.18;
import {DecoderBase} from "./decoders/Base.sol";

import {DataStructures} from "../src/core/libraries/DataStructures.sol";
import {Constants} from "../src/core/libraries/ConstantsGen.sol";

import {Registry} from "../src/core/messagebridge/Registry.sol";
import {Inbox} from "../src/core/messagebridge/Inbox.sol";
Expand All @@ -15,6 +16,8 @@ import {AvailabilityOracle} from "../src/core/availability_oracle/AvailabilityOr
import {NaiveMerkle} from "./merkle/Naive.sol";
import {MerkleTestUtil} from "./merkle/TestUtil.sol";

import {TxsDecoderHelper} from "./decoders/helpers/TxsDecoderHelper.sol";

/**
* Blocks are generated using the `integration_l1_publisher.test.ts` tests.
* Main use of these test is shorter cycles when updating the decoder contract.
Expand All @@ -25,6 +28,7 @@ contract RollupTest is DecoderBase {
Outbox internal outbox;
Rollup internal rollup;
MerkleTestUtil internal merkleTestUtil;
TxsDecoderHelper internal txsHelper;

AvailabilityOracle internal availabilityOracle;

Expand All @@ -38,6 +42,7 @@ contract RollupTest is DecoderBase {
registry.upgrade(address(rollup), address(inbox), address(outbox));

merkleTestUtil = new MerkleTestUtil();
txsHelper = new TxsDecoderHelper();
}

function testMixedBlock() public {
Expand Down Expand Up @@ -128,6 +133,7 @@ contract RollupTest is DecoderBase {
bytes memory header = full.block.header;
bytes32 archive = full.block.archive;
bytes memory body = full.block.body;
uint32 numTxs = full.block.numTxs;

// We jump to the time of the block.
vm.warp(full.block.decodedHeader.globalVariables.timestamp);
Expand All @@ -145,19 +151,25 @@ contract RollupTest is DecoderBase {

bytes32 l2ToL1MessageTreeRoot;
{
uint256 treeHeight =
merkleTestUtil.calculateTreeHeightFromSize(full.messages.l2ToL1Messages.length);
uint256 numTxsWithPadding = txsHelper.computeNumTxEffectsToPad(numTxs) + numTxs;
uint256 numMessagesWithPadding = numTxsWithPadding * Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX;

uint256 treeHeight = merkleTestUtil.calculateTreeHeightFromSize(numMessagesWithPadding);
NaiveMerkle tree = new NaiveMerkle(treeHeight);
for (uint256 i = 0; i < full.messages.l2ToL1Messages.length; i++) {
tree.insertLeaf(full.messages.l2ToL1Messages[i]);
for (uint256 i = 0; i < numMessagesWithPadding; i++) {
if (i < full.messages.l2ToL1Messages.length) {
tree.insertLeaf(full.messages.l2ToL1Messages[i]);
} else {
tree.insertLeaf(bytes32(0));
}
}

l2ToL1MessageTreeRoot = tree.computeRoot();
}

(bytes32 root,) = outbox.roots(full.block.decodedHeader.globalVariables.blockNumber);

assertEq(l2ToL1MessageTreeRoot, root);
assertEq(l2ToL1MessageTreeRoot, root, "Invalid l2 to l1 message tree root");

assertEq(rollup.archive(), archive, "Invalid archive");
}
Expand Down
3 changes: 3 additions & 0 deletions l1-contracts/test/decoders/Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ contract DecoderBase is Test {
bytes body;
DecodedHeader decodedHeader;
bytes header;
// Note: The following could be decoded from body but having it explicitaly here makes tests more robust against
// decoder changes
uint32 numTxs;
bytes32 publicInputsHash;
bytes32 txsEffectsHash;
}
Expand Down
35 changes: 35 additions & 0 deletions l1-contracts/test/decoders/Decoders.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,39 @@ contract DecodersTest is DecoderBase {
assertEq(bytesAdvanced, encodedLogs.length, "Advanced by an incorrect number of bytes");
assertEq(logsHash, referenceLogsHashFromIteration3, "Incorrect logs hash");
}

function testTxsDecoderCorrectlyComputesNumTxEffectsToPad() public {
// Minimum num txs is 2 so when there are no real txs we need to pad to 2
uint32 numTxEffects = 0;
uint32 paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2, "Incorrect number of tx effects to pad");

numTxEffects = 1;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 1 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 3;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 2 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 5;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 8;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 10;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 16;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 17;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 5 - numTxEffects, "Incorrect number of tx effects to pad");
}
}
4 changes: 4 additions & 0 deletions l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ contract TxsDecoderHelper {
{
return TxsDecoder.computeKernelLogsHash(0, _kernelLogs);
}

function computeNumTxEffectsToPad(uint32 _numTxEffects) external pure returns (uint32) {
return TxsDecoder.computeNumTxEffectsToPad(_numTxEffects);
}
}
38 changes: 15 additions & 23 deletions l1-contracts/test/fixtures/empty_block_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,26 @@
"sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
},
"messages": {
"l2ToL1Messages": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
"l2ToL1Messages": []
},
"block": {
"archive": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49",
"body": "0x0000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5",
"archive": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a",
"body": "0x00000000",
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa4316",
"txTreeHeight": 2,
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5"
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
},
"globalVariables": {
"blockNumber": 1,
"chainId": 31337,
"timestamp": 0,
"version": 1,
"coinbase": "0x5e65711eaf5606f1f42dd36579261833e54595ee",
"feeRecipient": "0x00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e"
"coinbase": "0x66440eb666440eb666440eb666440eb666440eb6",
"feeRecipient": "0x061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba"
},
"lastArchive": {
"nextAvailableLeafIndex": 1,
Expand All @@ -46,21 +37,22 @@
},
"partialStateReference": {
"noteHashTree": {
"nextAvailableLeafIndex": 256,
"nextAvailableLeafIndex": 128,
"root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb"
},
"nullifierTree": {
"nextAvailableLeafIndex": 384,
"nextAvailableLeafIndex": 256,
"root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278"
},
"publicDataTree": {
"nextAvailableLeafIndex": 192,
"nextAvailableLeafIndex": 128,
"root": "0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b"
}
}
}
},
"header": "0x1e3523d3bd50ae6204e1ec2ee1bdf8af4c6217ec80900052d2cf4259379dd130000000010000000000000000000000000000000000000000000000000000000000000002008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd500089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa43161864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000005e65711eaf5606f1f42dd36579261833e54595ee00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e",
"publicInputsHash": "0x009e67eb54715bba61c94f475f6d4bf81b775da316c2c9a6a12506851f760bf0"
"header": "0x1e3523d3bd50ae6204e1ec2ee1bdf8af4c6217ec80900052d2cf4259379dd13000000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000066440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba",
"publicInputsHash": "0x00b833c76dd93572e83879eeb4085a3cd71f24831384fb4d3fe531ed87b859e3",
"numTxs": 0
}
}
42 changes: 17 additions & 25 deletions l1-contracts/test/fixtures/empty_block_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,30 @@
"sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
},
"messages": {
"l2ToL1Messages": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
"l2ToL1Messages": []
},
"block": {
"archive": "0x045487d0ec498eb3f7f027715db8d67cc060604058bc5dd3e2e39fb47fe0ea17",
"body": "0x0000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5",
"archive": "0x0d53ab5014f578345d853cd208bda74db64358fef8e5f646240db05893f6e780",
"body": "0x00000000",
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa4316",
"txTreeHeight": 2,
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5"
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
},
"globalVariables": {
"blockNumber": 2,
"chainId": 31337,
"timestamp": 1711036059,
"timestamp": 1711637579,
"version": 1,
"coinbase": "0x5e65711eaf5606f1f42dd36579261833e54595ee",
"feeRecipient": "0x00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e"
"coinbase": "0x66440eb666440eb666440eb666440eb666440eb6",
"feeRecipient": "0x061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba"
},
"lastArchive": {
"nextAvailableLeafIndex": 2,
"root": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49"
"root": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a"
},
"stateReference": {
"l1ToL2MessageTree": {
Expand All @@ -46,21 +37,22 @@
},
"partialStateReference": {
"noteHashTree": {
"nextAvailableLeafIndex": 512,
"nextAvailableLeafIndex": 256,
"root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb"
},
"nullifierTree": {
"nextAvailableLeafIndex": 640,
"nextAvailableLeafIndex": 384,
"root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278"
},
"publicDataTree": {
"nextAvailableLeafIndex": 320,
"nextAvailableLeafIndex": 192,
"root": "0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b"
}
}
}
},
"header": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49000000020000000000000000000000000000000000000000000000000000000000000002008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd500089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa43161864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065fc569b5e65711eaf5606f1f42dd36579261833e54595ee00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e",
"publicInputsHash": "0x00e9cfdd839060c90c216e1cecd24c5570a84e380e2bc640fd9dbbb5b2dd0718"
"header": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a00000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006605844b66440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba",
"publicInputsHash": "0x00035031752fa374209f1ec4bc08613cae25ba65779c10130681421f6e71c6d9",
"numTxs": 0
}
}
17 changes: 9 additions & 8 deletions l1-contracts/test/fixtures/mixed_block_0.json

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions l1-contracts/test/fixtures/mixed_block_1.json

Large diffs are not rendered by default.

0 comments on commit e928c33

Please sign in to comment.