Skip to content

Commit be17101

Browse files
committed
chore(fast-inbox): delete legacy L1 inbox path (A-1386)
Deletes the legacy L1 Inbox path now that `propose` enforces streaming-inbox consumption (AZIP-22 Fast Inbox, FI-16). Stacked on `spl/a-1385-streaming-e2e`; part of the Fast Inbox stack (#24784..#24790 below this one). ## What is deleted - **Frontier trees**: the `trees` mapping, `forest`, `HEIGHT`/`SIZE`/`EMPTY_ROOT`, the per-message tree insert, `getRoot()`, and the whole `consume()` flow. - **LAG / inboxLag**: the `LAG` immutable and `_lag`/`_height` constructor args (the Inbox constructor is now `(rollup, feeAsset, version, bucketRingSize)`), `RollupConfigInput.inboxLag` and its `RollupCore` pass-through, and `Constants.L1_TO_L2_MSG_SUBTREE_HEIGHT` from the Inbox construction. - **Dead event field**: the `MessageSent.checkpointNumber` (former `inProgress`) argument, which became meaningless once `consume()` stopped advancing it. - **Orphaned errors**: `Inbox__Unauthorized`, `Inbox__MustBuildBeforeConsume`, `Rollup__InvalidInHash`. ## What is re-homed / kept - The compact message index now reads the current bucket's running total (`totalMsgCount`) instead of a parallel counter; `InboxState.inProgress` and `getInProgress()` are gone. - The 128-bit `rollingHash`, `InboxState.{rollingHash, totalMessagesInserted}`, `getState()`, and `getTotalMessagesInserted()` are **kept**: the node still consumes them for message sync and L1-reorg detection. Their removal is the node cleanup's job (FI-18). - `FrontierLib` is **kept** — it still backs the base-parity (`test/Parity.t.sol`) and merkle (`test/merkle/Frontier.t.sol`) tests, which are unrelated to the Inbox (parity-circuit territory, FI-17). The plan's "delete the file" assumption is contradicted by grep. ## TS follow-through - `ethereum` InboxContract: drop `getLag()`, drop the `MessageSent.checkpointNumber` decode, stop reading `inProgress`; `InboxContractState.treeInProgress` is now optional (no longer tracked on-chain). - Stop threading `inboxLag` through `queries.getL1ContractsConfig` and the L1 deploy env. The broader `AZTEC_INBOX_LAG` config sweep (`ethereum/src/config.ts`, `foundation`, `stdlib`, ~30 e2e configs) is deferred to FI-18, which explicitly owns it. - Archiver decode derives the message's checkpoint number from the compact index (the event no longer carries it), keeping the legacy per-checkpoint store shape untouched for FI-18. - Removed the obsolete `advanceInboxInProgress` cheat code + its inbox-drift tests, and the orphaned archiver `inHash`-mismatch sync test (the cross-check was removed at the flip). ## Gas Deleting the frontier insert is a large `sendL2Message` win. Whole-test gas (`forge test` on `InboxBuckets.t.sol`), before → after: | Case | Before | After | | --- | --- | --- | | First-ever message | 175,251 | 116,835 | | First message of a new L1 block | 329,460 | 195,555 | | Absorb into an existing bucket | 286,673 | 149,968 | | Rollover mid-block (256 messages) | 18,923,988 | 3,068,480 | Per-call `sendL2Message` gas after cleanup: first-ever 99,526; first-of-new-block 53,763; existing-bucket absorb 9,273; rollover 53,801. ## Testing - `forge build` + `forge test` green: 887 passed, 0 failed. This fixes 4 pre-existing baseline failures the flip stranded (`fee_portal`/`TokenPortal` deposit tests using tree-relative indices + the old event shape). - `@aztec/ethereum` builds clean; `config`/`queries` unit tests green. - `@aztec/archiver` has no self-owned type errors; `message_store` (36), `archiver-sync` (59), and the decode/struct suites (58) all pass. (Pre-existing `noir-protocol-circuits-types` stale-artifact errors are unaffected.) - e2e not run locally. The stability gate ("a few days of green e2e/networks before deleting the fallback") applies at merge time for this stacked line, not at PR creation. ## Review follow-up (phase-2 final review) Deleting the inbox-drift bot test left `bot.test.ts`'s `cheatCodes` variable unused (lint error); a follow-up commit removes it. ## Leftover sweep (post-review) - Corrected the `PublicInputArgs` natspec in `IRollup.sol`: it still described `previousInboxRollingHash` / `endInboxRollingHash` as deliberately unvalidated "until the Fast Inbox flip", but the flip (#24789, below this branch) added exactly that validation — `EpochProofLib` anchors the start boundary against the propose-time record, and the end boundary is covered transitively by the stored checkpoint header hashes. The comment now describes the implemented behavior. - The 128-bit rolling hash this PR deliberately kept (see "What is re-homed / kept") is now removed at the node-cleanup PR #24793, where its last TS readers disappear. Replaces #24791.
1 parent 3b2f02a commit be17101

33 files changed

Lines changed: 281 additions & 715 deletions

File tree

docs/docs-developers/docs/foundational-topics/ethereum-aztec-messaging/inbox.md

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,10 @@ These functions allow you to query the current state of the Inbox.
3535

3636
| Function | Returns | Description |
3737
| -------------------------- | ----------------- | ------------------------------------------------ |
38-
| `getRoot(uint256)` | `bytes32` | Returns the root of a message tree for a given checkpoint number. |
39-
| `getState()` | `InboxState` | Returns the current inbox state (rolling hash, total messages inserted, in-progress checkpoint). |
38+
| `getState()` | `InboxState` | Returns the current inbox state (rolling hash, total messages inserted). |
4039
| `getTotalMessagesInserted()` | `uint64` | Returns the total number of messages inserted into the inbox. |
41-
| `getInProgress()` | `uint64` | Returns the checkpoint number currently being filled. |
4240
| `getFeeAssetPortal()` | `address` | Returns the address of the Fee Juice portal. |
4341

44-
## Internal functions
45-
46-
:::note
47-
The following functions are only callable by the Rollup contract and are documented here for completeness.
48-
:::
49-
50-
### `consume()`
51-
52-
Consumes a message tree for a given checkpoint number.
53-
54-
#include_code consume l1-contracts/src/core/interfaces/messagebridge/IInbox.sol solidity
55-
56-
| Name | Type | Description |
57-
| ----------- | --------- | ---------------------------------------- |
58-
| _toConsume | `uint256` | The checkpoint number to consume. |
59-
| ReturnValue | `bytes32` | The root of the consumed message tree. |
60-
61-
#### Edge cases
62-
63-
- Will revert with `Inbox__Unauthorized()` if `msg.sender != ROLLUP`.
64-
- Will revert with `Inbox__MustBuildBeforeConsume()` if trying to consume a checkpoint that hasn't been built yet.
65-
6642
## Related pages
6743

6844
- [Outbox](./outbox.md) - L2 to L1 message passing

docs/examples/ts/aave_bridge/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ const INBOX_ABI = [
347347
type: "event",
348348
name: "MessageSent",
349349
inputs: [
350-
{ name: "checkpointNumber", type: "uint256", indexed: true },
351350
{ name: "index", type: "uint256", indexed: false },
352351
{ name: "hash", type: "bytes32", indexed: true },
353352
{ name: "rollingHash", type: "bytes16", indexed: false },

docs/examples/ts/example_swap/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ const INBOX_ABI = [
259259
type: "event",
260260
name: "MessageSent",
261261
inputs: [
262-
{ name: "checkpointNumber", type: "uint256", indexed: true },
263262
{ name: "index", type: "uint256", indexed: false },
264263
{ name: "hash", type: "bytes32", indexed: true },
265264
{ name: "rollingHash", type: "bytes16", indexed: false },

docs/examples/ts/token_bridge/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ const INBOX_ABI = [
165165
type: "event",
166166
name: "MessageSent",
167167
inputs: [
168-
{ name: "checkpointNumber", type: "uint256", indexed: true },
169168
{ name: "index", type: "uint256", indexed: false },
170169
{ name: "hash", type: "bytes32", indexed: true },
171170
{ name: "rollingHash", type: "bytes16", indexed: false },

l1-contracts/script/deploy/RollupConfiguration.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ contract RollupConfiguration is IRollupConfiguration, Test {
110110
config.targetCommitteeSize = vm.envUint("AZTEC_TARGET_COMMITTEE_SIZE");
111111
config.lagInEpochsForValidatorSet = vm.envUint("AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET");
112112
config.lagInEpochsForRandao = vm.envUint("AZTEC_LAG_IN_EPOCHS_FOR_RANDAO");
113-
config.inboxLag = vm.envUint("AZTEC_INBOX_LAG");
114113
config.aztecProofSubmissionEpochs = vm.envUint("AZTEC_PROOF_SUBMISSION_EPOCHS");
115114
config.localEjectionThreshold = vm.envUint("AZTEC_LOCAL_EJECTION_THRESHOLD");
116115
config.slashingQuorum = vm.envOr("AZTEC_SLASHING_QUORUM", slashingRoundSize / 2 + 1);

l1-contracts/src/core/RollupCore.sol

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {IStakingCore} from "@aztec/core/interfaces/IStaking.sol";
1515
import {IValidatorSelectionCore} from "@aztec/core/interfaces/IValidatorSelection.sol";
1616
import {IInbox} from "@aztec/core/interfaces/messagebridge/IInbox.sol";
1717
import {IOutbox} from "@aztec/core/interfaces/messagebridge/IOutbox.sol";
18-
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
1918
import {CommitteeAttestations} from "@aztec/core/libraries/rollup/AttestationLib.sol";
2019
import {Errors} from "@aztec/core/libraries/Errors.sol";
2120
import {EpochProofExtLib} from "@aztec/core/libraries/rollup/EpochProofExtLib.sol";
@@ -620,18 +619,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
620619
rollupStore.config.epochProofVerifier = _epochProofVerifier;
621620
rollupStore.config.version = _config.version;
622621

623-
IInbox inbox = IInbox(
624-
address(
625-
new Inbox(
626-
address(this),
627-
_feeAsset,
628-
_config.version,
629-
Constants.L1_TO_L2_MSG_SUBTREE_HEIGHT,
630-
_config.inboxLag,
631-
INBOX_BUCKET_RING_SIZE
632-
)
633-
)
634-
);
622+
IInbox inbox = IInbox(address(new Inbox(address(this), _feeAsset, _config.version, INBOX_BUCKET_RING_SIZE)));
635623

636624
rollupStore.config.inbox = inbox;
637625
rollupStore.config.outbox = IOutbox(address(new Outbox(address(this), _config.version)));

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ struct PublicInputArgs {
2727
bytes32 previousArchive;
2828
bytes32 endArchive;
2929
bytes32 outHash;
30-
// Inbox rolling-hash chain segment consumed across the proven epoch (AZIP-22 Fast Inbox). Deliberately UNVALIDATED
31-
// until the Fast Inbox flip, when they get checked against per-checkpoint records written at propose; for now they
32-
// are only passed through to the proof's public inputs.
30+
// Inbox rolling-hash chain segment consumed across the proven epoch (AZIP-22 Fast Inbox). Both boundaries are
31+
// anchored at proof submission against the rolling hashes recorded at propose for checkpoints start - 1 and end.
3332
bytes32 previousInboxRollingHash;
3433
bytes32 endInboxRollingHash;
3534
address proverId;
@@ -84,7 +83,6 @@ struct RollupConfigInput {
8483
RewardBoostConfig rewardBoostConfig;
8584
StakingQueueConfig stakingQueueConfig;
8685
uint256 localEjectionThreshold;
87-
uint256 inboxLag;
8886
}
8987

9088
struct RollupConfig {

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

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ pragma solidity >=0.8.27;
55
import {DataStructures} from "../../libraries/DataStructures.sol";
66

77
// Maximum number of messages a single bucket can hold before further messages in the same L1 block spill over
8-
// into the next bucket. Matches the number of L1 to L2 messages a single L2 block can insert once the streaming
9-
// inbox is live, so any one bucket is always consumable by one block.
8+
// into the next bucket. Matches the number of L1 to L2 messages a single L2 block can insert, so any one bucket
9+
// is always consumable by one block.
1010
uint256 constant MAX_MSGS_PER_BUCKET = 256;
1111

1212
/**
@@ -16,16 +16,14 @@ uint256 constant MAX_MSGS_PER_BUCKET = 256;
1616
*/
1717
interface IInbox {
1818
struct InboxState {
19-
// Rolling hash of all messages inserted into the inbox.
20-
// Used by clients to check for consistency.
21-
// TODO: remove once the streaming inbox (AZIP-22 Fast Inbox) flips on and clients rely on the
22-
// consensus rolling hash tracked in the buckets instead.
19+
// Legacy 128-bit keccak rolling hash of all messages inserted into the inbox. Consumed only by the
20+
// node for message sync and L1-reorg detection.
21+
// TODO: remove once the node relies on the full-width consensus rolling hash tracked in the buckets
22+
// instead (AZIP-22 Fast Inbox).
2323
bytes16 rollingHash;
24-
// This value is not used much by the contract, but it is useful for synching the node faster
25-
// as it can more easily figure out if it can just skip looking for events for a time period.
24+
// Cumulative number of messages inserted into the inbox. Useful for synching the node faster as it can
25+
// more easily figure out if it can just skip looking for events for a time period.
2626
uint64 totalMessagesInserted;
27-
// Number of a tree which is currently being filled
28-
uint64 inProgress;
2927
}
3028

3129
/**
@@ -50,20 +48,14 @@ interface IInbox {
5048

5149
/**
5250
* @notice Emitted when a message is sent
53-
* @param checkpointNumber - The checkpoint number in which the message is included
54-
* @param index - The index of the message in the L1 to L2 messages tree
51+
* @param index - The compact cumulative index of the message in the Inbox insertion order
5552
* @param hash - The hash of the message
56-
* @param rollingHash - The rolling hash of all messages inserted into the inbox
53+
* @param rollingHash - The legacy 128-bit rolling hash of all messages inserted into the inbox
5754
* @param inboxRollingHash - The consensus rolling hash (truncated sha256 chain) after this message
5855
* @param bucketSeq - The sequence number of the bucket this message was absorbed into
5956
*/
6057
event MessageSent(
61-
uint256 indexed checkpointNumber,
62-
uint256 index,
63-
bytes32 indexed hash,
64-
bytes16 rollingHash,
65-
bytes32 inboxRollingHash,
66-
uint256 bucketSeq
58+
uint256 index, bytes32 indexed hash, bytes16 rollingHash, bytes32 inboxRollingHash, uint256 bucketSeq
6759
);
6860

6961
// docs:start:send_l1_to_l2_message
@@ -74,37 +66,19 @@ interface IInbox {
7466
* @param _content - The content of the message (application specific)
7567
* @param _secretHash - The secret hash of the message (make it possible to hide when a specific message is consumed
7668
* on L2)
77-
* @return The key of the message in the set and its leaf index in the tree
69+
* @return The key of the message in the set and its compact cumulative index
7870
*/
7971
function sendL2Message(DataStructures.L2Actor memory _recipient, bytes32 _content, bytes32 _secretHash)
8072
external
8173
returns (bytes32, uint256);
8274
// docs:end:send_l1_to_l2_message
8375

84-
// docs:start:consume
85-
/**
86-
* @notice Consumes the current tree, and starts a new one if needed
87-
* @dev Only callable by the rollup contract
88-
* @dev In the first iteration we return empty tree root because first checkpoint's messages tree is always
89-
* empty because there has to be a 1 checkpoint lag to prevent sequencer DOS attacks
90-
*
91-
* @param _toConsume - The checkpoint number to consume
92-
*
93-
* @return The root of the consumed tree
94-
*/
95-
function consume(uint256 _toConsume) external returns (bytes32);
96-
// docs:end:consume
97-
9876
function getFeeAssetPortal() external view returns (address);
9977

100-
function getRoot(uint256 _checkpointNumber) external view returns (bytes32);
101-
10278
function getState() external view returns (InboxState memory);
10379

10480
function getTotalMessagesInserted() external view returns (uint64);
10581

106-
function getInProgress() external view returns (uint64);
107-
10882
/**
10983
* @notice Returns the sequence number of the bucket currently accumulating messages
11084
* @return The current bucket sequence number

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@ library Errors {
2222
error DevNet__InvalidProposer(address expected, address actual); // 0x11e6e6f7
2323

2424
// Inbox
25-
error Inbox__Unauthorized(); // 0xe5336a6b
2625
error Inbox__ActorTooLarge(bytes32 actor); // 0xa776a06e
2726
error Inbox__VersionMismatch(uint256 expected, uint256 actual); // 0x47452014
2827
error Inbox__ContentTooLarge(bytes32 content); // 0x47452014
2928
error Inbox__SecretHashTooLarge(bytes32 secretHash); // 0xecde7e2c
30-
error Inbox__MustBuildBeforeConsume(); // 0xc4901999
3129
error Inbox__BucketOutOfWindow(uint256 seq, uint256 current); // 0xfee255b7
3230

3331
// Outbox
@@ -58,7 +56,6 @@ library Errors {
5856
error Rollup__InvalidCheckpointHeader(bytes32 expected, bytes32 actual);
5957
error Rollup__InvalidCheckpointHeaderCount(uint256 expected, uint256 actual);
6058
error Rollup__InvalidCheckpointNumber(uint256 expected, uint256 actual); // 0xd1ba9bfa
61-
error Rollup__InvalidInHash(bytes32 expected, bytes32 actual); // 0xcd6f4233
6259
error Rollup__InvalidInboxRollingHash(bytes32 expected, bytes32 actual); // 0xed1f7bb5
6360
error Rollup__InvalidPreviousInboxRollingHash(bytes32 expected, bytes32 actual); // 0x2fe7cae5
6461
error Rollup__InvalidEndInboxRollingHash(bytes32 expected, bytes32 actual); // 0x4a9cdb72

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ library ProposeLib {
142142
* - Checkpoint header validations (see validateHeader function for details)
143143
* - Proposer signature is valid for designated slot proposer:
144144
* Errors.ValidatorSelection__MissingProposerSignature
145-
* - Inbox hash matches expected value: Errors.Rollup__InvalidInHash
145+
* - Streaming Inbox consumption is valid: Errors.Rollup__InvalidInboxRollingHash
146146
* - Archive root is within the scalar field: Errors.Rollup__FieldElementOutOfRange
147147
*
148148
* Validations NOT performed:
@@ -154,7 +154,7 @@ library ProposeLib {
154154
* - Store archive root for the new checkpoint number
155155
* - Store checkpoint metadata in circular storage (TempCheckpointLog)
156156
* - Update L1 gas fee oracle
157-
* - Consume inbox messages
157+
* - Validate streaming Inbox consumption against the parent checkpoint
158158
* - Setup epoch for validator selection (first block of the epoch)
159159
*
160160
* @param _args - The arguments to propose the checkpoint
@@ -401,8 +401,8 @@ library ProposeLib {
401401

402402
/**
403403
* @notice Validates a checkpoint's Inbox consumption against the streaming inbox buckets and returns how
404-
* far consumption has reached. Not yet called from propose(): the legacy `consume()`/`inHash` flow
405-
* remains the enforced path until the streaming inbox (AZIP-22 Fast Inbox) flips on.
404+
* far consumption has reached. Called from propose() as the enforced consumption path (AZIP-22 Fast
405+
* Inbox).
406406
*
407407
* @dev Read-only; performs no Inbox write. Checks, in order:
408408
* 1. The checkpoint header's `inboxRollingHash` must equal the rolling hash snapshotted in the Inbox

0 commit comments

Comments
 (0)