Skip to content

Commit d24b4f5

Browse files
committed
Aggregate out hashes and set on L1 per epoch.
1 parent 8cb3be4 commit d24b4f5

File tree

121 files changed

+8748
-8559
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+8748
-8559
lines changed

l1-contracts/src/core/interfaces/IRollup.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {IERC20} from "@oz/token/ERC20/IERC20.sol";
2626
struct PublicInputArgs {
2727
bytes32 previousArchive;
2828
bytes32 endArchive;
29+
bytes32 outHash;
2930
address proverId;
3031
}
3132

l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pragma solidity >=0.8.27;
44

55
import {DataStructures} from "../../libraries/DataStructures.sol";
6+
import {Epoch} from "../../libraries/TimeLib.sol";
67

78
/**
89
* @title IOutbox
@@ -11,21 +12,18 @@ import {DataStructures} from "../../libraries/DataStructures.sol";
1112
* and will be consumed by the portal contracts.
1213
*/
1314
interface IOutbox {
14-
event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root);
15-
event MessageConsumed(
16-
uint256 indexed l2BlockNumber, bytes32 indexed root, bytes32 indexed messageHash, uint256 leafId
17-
);
15+
event RootAdded(Epoch indexed epoch, bytes32 indexed root);
16+
event MessageConsumed(Epoch indexed epoch, bytes32 indexed root, bytes32 indexed messageHash, uint256 leafId);
1817

1918
// docs:start:outbox_insert
2019
/**
21-
* @notice Inserts the root of a merkle tree containing all of the L2 to L1 messages in
22-
* a block specified by _l2BlockNumber.
20+
* @notice Inserts the root of a merkle tree containing all of the L2 to L1 messages in an epoch specified by _epoch.
2321
* @dev Only callable by the rollup contract
2422
* @dev Emits `RootAdded` upon inserting the root successfully
25-
* @param _l2BlockNumber - The L2 Block Number in which the L2 to L1 messages reside
23+
* @param _epoch - The epoch in which the L2 to L1 messages reside
2624
* @param _root - The merkle root of the tree where all the L2 to L1 messages are leaves
2725
*/
28-
function insert(uint256 _l2BlockNumber, bytes32 _root) external;
26+
function insert(Epoch _epoch, bytes32 _root) external;
2927
// docs:end:outbox_insert
3028

3129
// docs:start:outbox_consume
@@ -34,37 +32,36 @@ interface IOutbox {
3432
* @dev Only useable by portals / recipients of messages
3533
* @dev Emits `MessageConsumed` when consuming messages
3634
* @param _message - The L2 to L1 message
37-
* @param _l2BlockNumber - The block number specifying the block that contains the message we want to consume
38-
* @param _leafIndex - The index inside the merkle tree where the message is located
39-
* @param _path - The sibling path used to prove inclusion of the message, the _path length directly depends
40-
* on the total amount of L2 to L1 messages in the block. i.e. the length of _path is equal to the depth of the
41-
* L1 to L2 message tree.
35+
* @param _epoch - The epoch that contains the message we want to consume
36+
* @param _leafIndex - The index at the level in the wonky tree where the message is located
37+
* @param _path - The sibling path used to prove inclusion of the message, the _path length depends
38+
* on the location of the L2 to L1 message in the wonky tree.
4239
*/
4340
function consume(
4441
DataStructures.L2ToL1Msg calldata _message,
45-
uint256 _l2BlockNumber,
42+
Epoch _epoch,
4643
uint256 _leafIndex,
4744
bytes32[] calldata _path
4845
) external;
4946
// docs:end:outbox_consume
5047

5148
// docs:start:outbox_has_message_been_consumed_at_block_and_index
5249
/**
53-
* @notice Checks to see if an L2 to L1 message in a specific block has been consumed
50+
* @notice Checks to see if an L2 to L1 message in a specific epoch has been consumed
5451
* @dev - This function does not throw. Out-of-bounds access is considered valid, but will always return false
55-
* @param _l2BlockNumber - The block number specifying the block that contains the message we want to check
52+
* @param _epoch - The epoch that contains the message we want to check
5653
* @param _leafId - The unique id of the message leaf
5754
*/
58-
function hasMessageBeenConsumedAtBlock(uint256 _l2BlockNumber, uint256 _leafId) external view returns (bool);
55+
function hasMessageBeenConsumedAtEpoch(Epoch _epoch, uint256 _leafId) external view returns (bool);
5956
// docs:end:outbox_has_message_been_consumed_at_block_and_index
6057

6158
/**
62-
* @notice Fetch the root data for a given block number
63-
* Returns (0, 0) if the block is not proven
59+
* @notice Fetch the root data for a given epoch
60+
* Returns (0, 0) if the epoch is not proven
6461
*
65-
* @param _l2BlockNumber - The block number to fetch the root data for
62+
* @param _epoch - The epoch to fetch the root data for
6663
*
6764
* @return bytes32 - The root of the merkle tree containing the L2 to L1 messages
6865
*/
69-
function getRootData(uint256 _l2BlockNumber) external view returns (bytes32);
66+
function getRootData(Epoch _epoch) external view returns (bytes32);
7067
}

l1-contracts/src/core/libraries/ConstantsGen.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ library Constants {
2424
14_269_942_583_723_164_841_365_114_274_712_143_548_835_546_030_057_296_325_580_016_468_921_911_294_613;
2525
uint256 internal constant FEE_JUICE_ADDRESS = 5;
2626
uint256 internal constant BLS12_POINT_COMPRESSED_BYTES = 48;
27-
uint256 internal constant PROPOSED_BLOCK_HEADER_LENGTH_BYTES = 284;
28-
uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 158;
27+
uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 159;
2928
uint256 internal constant NUM_MSGS_PER_BASE_PARITY = 4;
3029
uint256 internal constant NUM_BASE_PARITY_PER_ROOT_PARITY = 4;
3130
}

l1-contracts/src/core/libraries/Errors.sol

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,9 @@ library Errors {
4343
uint32 storedDeadline,
4444
uint32 deadlinePassed
4545
); // 0x5e789f34
46-
error Outbox__RootAlreadySetAtBlock(uint256 l2BlockNumber); // 0x3eccfd3e
4746
error Outbox__InvalidRecipient(address expected, address actual); // 0x57aad581
48-
error Outbox__AlreadyNullified(uint256 l2BlockNumber, uint256 leafIndex); // 0xfd71c2d4
49-
error Outbox__NothingToConsumeAtBlock(uint256 l2BlockNumber); // 0xa4508f22
50-
error Outbox__BlockNotProven(uint256 l2BlockNumber); // 0x0e194a6d
51-
error Outbox__BlockAlreadyProven(uint256 l2BlockNumber);
47+
error Outbox__AlreadyNullified(Epoch epoch, uint256 leafIndex); // 0xfd71c2d4
48+
error Outbox__NothingToConsumeAtEpoch(Epoch epoch); // 0xa4508f22
5249
error Outbox__PathTooLong();
5350
error Outbox__LeafIndexOutOfBounds(uint256 leafIndex, uint256 pathLength);
5451

l1-contracts/src/core/libraries/rollup/EpochProofLib.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ library EpochProofLib {
119119
rollupStore.tips =
120120
rollupStore.tips.updateProvenBlockNumber(Math.max(rollupStore.tips.getProvenBlockNumber(), _args.end));
121121

122+
// Handle L2->L1 message processing
123+
if (_args.args.outHash != bytes32(0)) {
124+
// Insert L2->L1 messages into outbox for consumption.
125+
rollupStore.config.outbox.insert(endEpoch, _args.args.outHash);
126+
}
127+
122128
RewardLib.handleRewardsAndFees(_args, endEpoch);
123129

124130
emit IRollupCore.L2ProofVerified(_args.end, _args.args.proverId);
@@ -171,30 +177,33 @@ library EpochProofLib {
171177
// struct RootRollupPublicInputs {
172178
// previous_archive_root: Field,
173179
// end_archive_root: Field,
180+
// out_hash: Field,
174181
// proposedBlockHeaderHashes: [Field; Constants.AZTEC_MAX_EPOCH_DURATION],
175182
// fees: [FeeRecipient; Constants.AZTEC_MAX_EPOCH_DURATION],
176183
// chain_id: Field,
177184
// version: Field,
178185
// vk_tree_root: Field,
179186
// protocol_contracts_hash: Field,
180187
// prover_id: Field,
181-
// blob_public_inputs: FinalBlobAccumulatorPublicInputs,
188+
// blob_public_inputs: FinalBlobAccumulator,
182189
// }
183190
{
184191
// previous_archive.root: the previous archive tree root
185192
publicInputs[0] = _args.previousArchive;
186193

187194
// end_archive.root: the new archive tree root
188195
publicInputs[1] = _args.endArchive;
196+
197+
publicInputs[2] = _args.outHash;
189198
}
190199

191200
uint256 numBlocks = _end - _start + 1;
192201

193202
for (uint256 i = 0; i < numBlocks; i++) {
194-
publicInputs[2 + i] = STFLib.getHeaderHash(_start + i);
203+
publicInputs[3 + i] = STFLib.getHeaderHash(_start + i);
195204
}
196205

197-
uint256 offset = 2 + Constants.AZTEC_MAX_EPOCH_DURATION;
206+
uint256 offset = 3 + Constants.AZTEC_MAX_EPOCH_DURATION;
198207

199208
uint256 feesLength = Constants.AZTEC_MAX_EPOCH_DURATION * 2;
200209
// fees[2n to 2n + 1]: a fee element, which contains of a recipient and a value
@@ -249,7 +258,6 @@ library EpochProofLib {
249258
publicInputs[offset] = bytes32(uint256(uint248(bytes31((_blobPublicInputs[96:127])))));
250259
// c[1]
251260
publicInputs[offset + 1] = bytes32(uint256(uint136(bytes17((_blobPublicInputs[127:144])))));
252-
offset += 2;
253261

254262
return publicInputs;
255263
}

l1-contracts/src/core/libraries/rollup/ProposeLib.sol

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct ValidateHeaderArgs {
7676
* - Validator selection and proposer verification
7777
* - Fee calculation and mana consumption tracking
7878
* - State transitions and archive updates
79-
* - Message processing between L1 and L2 via the Inbox and Outbox contracts
79+
* - L1 to L2 message processing via the Inbox
8080
*
8181
* The proposal flow operates within Aztec's time-based model where:
8282
* - Each slot has a designated proposer selected from the validator set
@@ -123,7 +123,7 @@ library ProposeLib {
123123
* Note that some validations and processes are disabled if the chain is configured to run without
124124
* transactions, such as during ignition phase:
125125
* - No fee header computation or L1 gas fee oracle update
126-
* - No inbox message consumption or outbox message insertion
126+
* - No inbox message consumption
127127
*
128128
* Validations performed:
129129
* - Blob commitments against provided blob data: Errors.Rollup__InvalidBlobHash,
@@ -143,7 +143,6 @@ library ProposeLib {
143143
* - Store block metadata in circular storage (TempBlockLog)
144144
* - Update L1 gas fee oracle (when txs enabled)
145145
* - Consume inbox messages (when txs enabled)
146-
* - Insert outbox messages (when txs enabled)
147146
* - Setup epoch for validator selection (first block of the epoch)
148147
*
149148
* @param _args - The arguments to propose the block
@@ -294,22 +293,16 @@ library ProposeLib {
294293
})
295294
);
296295

297-
// Handle L1<->L2 message processing (only when transactions are enabled)
296+
// Handle L1->L2 message processing (only when transactions are enabled)
298297
if (v.isTxsEnabled) {
299-
// Since ignition will have no transactions there will be no method to consume or output message.
298+
// Since ignition will have no transactions there will be no method to consume messages.
300299
// Therefore we can ignore it as long as mana target is zero.
301300
// Since the inbox is async, it must enforce its own check to not try to insert if ignition.
302301

303302
// Consume pending L1->L2 messages and validate against header commitment
304303
// @note The block number here will always be >=1 as the genesis block is at 0
305304
v.inHash = rollupStore.config.inbox.consume(blockNumber);
306-
require(
307-
v.header.contentCommitment.inHash == v.inHash,
308-
Errors.Rollup__InvalidInHash(v.inHash, v.header.contentCommitment.inHash)
309-
);
310-
311-
// Insert L2->L1 messages into outbox for later consumption
312-
rollupStore.config.outbox.insert(blockNumber, v.header.contentCommitment.outHash);
305+
require(v.header.inHash == v.inHash, Errors.Rollup__InvalidInHash(v.inHash, v.header.inHash));
313306
}
314307

315308
// Emit event for external listeners. Nodes rely on this event to update their state.
@@ -363,8 +356,8 @@ library ProposeLib {
363356
require(timestamp <= currentTime, Errors.Rollup__TimestampInFuture(currentTime, timestamp));
364357

365358
require(
366-
_args.flags.ignoreDA || _args.header.contentCommitment.blobsHash == _args.blobsHashesCommitment,
367-
Errors.Rollup__UnavailableTxs(_args.header.contentCommitment.blobsHash)
359+
_args.flags.ignoreDA || _args.header.blobsHash == _args.blobsHashesCommitment,
360+
Errors.Rollup__UnavailableTxs(_args.header.blobsHash)
368361
);
369362

370363
require(_args.header.gasFees.feePerDaGas == 0, Errors.Rollup__NonZeroDaFee());

l1-contracts/src/core/libraries/rollup/ProposedHeaderLib.sol

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,10 @@ struct GasFees {
2929
uint128 feePerL2Gas;
3030
}
3131

32-
struct ContentCommitment {
33-
bytes32 blobsHash;
34-
bytes32 inHash;
35-
bytes32 outHash;
36-
}
37-
3832
struct ProposedHeader {
3933
bytes32 lastArchiveRoot;
40-
ContentCommitment contentCommitment;
34+
bytes32 blobsHash;
35+
bytes32 inHash;
4136
Slot slotNumber;
4237
Timestamp timestamp;
4338
address coinbase;
@@ -67,9 +62,8 @@ library ProposedHeaderLib {
6762
return Hash.sha256ToField(
6863
abi.encodePacked(
6964
_header.lastArchiveRoot,
70-
_header.contentCommitment.blobsHash,
71-
_header.contentCommitment.inHash,
72-
_header.contentCommitment.outHash,
65+
_header.blobsHash,
66+
_header.inHash,
7367
_header.slotNumber,
7468
Timestamp.unwrap(_header.timestamp).toUint64(),
7569
_header.coinbase,

0 commit comments

Comments
 (0)