Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions l1-contracts/scripts/constants-codegen/solidity.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[
"MAX_FIELD_VALUE",
"L1_TO_L2_MSG_SUBTREE_HEIGHT",
"MAX_L1_TO_L2_MSGS_PER_CHECKPOINT",
"INBOX_LAG_SECONDS",
"MAX_L2_TO_L1_MSGS_PER_TX",
"INITIAL_CHECKPOINT_NUMBER",
"MAX_CHECKPOINTS_PER_EPOCH",
Expand Down
15 changes: 4 additions & 11 deletions l1-contracts/src/core/libraries/rollup/ProposeLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IInbox, MAX_MSGS_PER_BUCKET} from "@aztec/core/interfaces/messagebridge/
import {TempCheckpointLog} from "@aztec/core/libraries/compressed-data/CheckpointLog.sol";
import {FeeHeader} from "@aztec/core/libraries/compressed-data/fees/FeeStructs.sol";
import {ChainTipsLib, CompressedChainTips} from "@aztec/core/libraries/compressed-data/Tips.sol";
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {CommitteeAttestations} from "@aztec/core/libraries/rollup/AttestationLib.sol";
import {CoordinationSignatureLib} from "@aztec/core/libraries/rollup/CoordinationSignatureLib.sol";
Expand All @@ -22,14 +23,6 @@ import {SafeCast} from "@oz/utils/math/SafeCast.sol";
import {ProposedHeader, ProposedHeaderLib} from "./ProposedHeaderLib.sol";
import {STFLib} from "./STFLib.sol";

// Streaming-inbox protocol constants (AZIP-22 Fast Inbox). These mirror the protocol circuit constants and
// should move into the generated Constants library once the Solidity emitter includes them.
// Minimum bucket age, in seconds, at the start of a checkpoint's build frame for its consumption to be
// mandatory. One L1 slot: validators cannot be required to act on buckets they may not have seen.
uint256 constant INBOX_LAG_SECONDS = 12;
// Maximum number of L1 to L2 messages a single checkpoint can insert.
uint256 constant MAX_L1_TO_L2_MSGS_PER_CHECKPOINT = 1024;

struct ProposeArgs {
bytes32 archive;
OracleInput oracleInput;
Expand Down Expand Up @@ -465,17 +458,17 @@ library ProposeLib {
);

require(
bucket.totalMsgCount - _parentTotalMsgCount <= MAX_L1_TO_L2_MSGS_PER_CHECKPOINT,
bucket.totalMsgCount - _parentTotalMsgCount <= Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT,
Errors.Rollup__TooManyInboxMessagesConsumed(bucket.totalMsgCount - _parentTotalMsgCount)
);

if (_bucketHint < _inbox.getCurrentBucketSeq()) {
IInbox.InboxBucket memory next = _inbox.getBucket(_bucketHint + 1);
Timestamp buildFrameStart = TimeLib.toTimestamp(_slotNumber - Slot.wrap(1));
Timestamp cutoff = buildFrameStart - Timestamp.wrap(INBOX_LAG_SECONDS);
Timestamp cutoff = buildFrameStart - Timestamp.wrap(Constants.INBOX_LAG_SECONDS);
require(
next.timestamp > Timestamp.unwrap(cutoff)
|| next.totalMsgCount - _parentTotalMsgCount > MAX_L1_TO_L2_MSGS_PER_CHECKPOINT,
|| next.totalMsgCount - _parentTotalMsgCount > Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT,
Errors.Rollup__UnconsumedInboxMessages(_bucketHint + 1)
);
}
Expand Down
23 changes: 11 additions & 12 deletions l1-contracts/test/rollup/ProposeInboxConsumption.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import {Test} from "forge-std/Test.sol";
import {TestERC20} from "src/mock/TestERC20.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {IInbox, MAX_MSGS_PER_BUCKET} from "@aztec/core/interfaces/messagebridge/IInbox.sol";
import {
ProposeLib,
INBOX_LAG_SECONDS,
MAX_L1_TO_L2_MSGS_PER_CHECKPOINT
} from "@aztec/core/libraries/rollup/ProposeLib.sol";
import {ProposeLib} from "@aztec/core/libraries/rollup/ProposeLib.sol";
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
import {TimeLib, Slot, Timestamp} from "@aztec/core/libraries/TimeLib.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
Expand Down Expand Up @@ -50,7 +47,7 @@ contract ProposeInboxConsumptionTest is Test {
// Start of the build frame for a checkpoint proposed in SLOT: it is built during the previous slot.
uint256 internal buildFrameStart = GENESIS_TIME + (Slot.unwrap(SLOT) - 1) * SLOT_DURATION;
// Buckets at or before the cutoff must be consumed by the checkpoint.
uint256 internal cutoff = buildFrameStart - INBOX_LAG_SECONDS;
uint256 internal cutoff = buildFrameStart - Constants.INBOX_LAG_SECONDS;

function setUp() public {
vm.warp(GENESIS_TIME);
Expand Down Expand Up @@ -125,7 +122,7 @@ contract ProposeInboxConsumptionTest is Test {
// One more message than the checkpoint cap, all before the cutoff. They spill over into buckets
// 1..4 of 256 (the per-bucket cap) plus bucket 5 with the single excess message.
vm.warp(cutoff - 100);
_sendMany(MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
_sendMany(Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
assertEq(inbox.getCurrentBucketSeq(), 5, "expected five buckets");

vm.warp(GENESIS_TIME + Slot.unwrap(SLOT) * SLOT_DURATION);
Expand All @@ -134,12 +131,12 @@ contract ProposeInboxConsumptionTest is Test {
// even though it is old.
bytes32 endHash = inbox.getBucket(4).rollingHash;
uint256 consumed = rollup.validateInboxConsumption(inbox, endHash, 4, SLOT, 0);
assertEq(consumed, MAX_L1_TO_L2_MSGS_PER_CHECKPOINT, "consumed the full cap");
assertEq(consumed, Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT, "consumed the full cap");
}

function testNoCapEscapeAtExactCap() public {
vm.warp(cutoff - 100);
_sendMany(MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
_sendMany(Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);

vm.warp(GENESIS_TIME + Slot.unwrap(SLOT) * SLOT_DURATION);

Expand All @@ -154,7 +151,7 @@ contract ProposeInboxConsumptionTest is Test {
// Same layout as testCapEscape, but the parent checkpoint had already consumed one message:
// buckets 2..5 then hold cap messages total, which fit in one checkpoint, so no escape from bucket 1.
vm.warp(cutoff - 100);
_sendMany(MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
_sendMany(Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);

vm.warp(GENESIS_TIME + Slot.unwrap(SLOT) * SLOT_DURATION);

Expand Down Expand Up @@ -288,14 +285,16 @@ contract ProposeInboxConsumptionTest is Test {
// One more message than the checkpoint cap, all before the cutoff, referenced in a single proposal from
// a fresh parent: the consumed delta exceeds what the circuits can insert.
vm.warp(cutoff - 100);
_sendMany(MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
_sendMany(Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1);
assertEq(inbox.getCurrentBucketSeq(), 5, "expected five buckets");

bytes32 endHash = inbox.getBucket(5).rollingHash;

vm.warp(GENESIS_TIME + Slot.unwrap(SLOT) * SLOT_DURATION);
vm.expectRevert(
abi.encodeWithSelector(Errors.Rollup__TooManyInboxMessagesConsumed.selector, MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1)
abi.encodeWithSelector(
Errors.Rollup__TooManyInboxMessagesConsumed.selector, Constants.MAX_L1_TO_L2_MSGS_PER_CHECKPOINT + 1
)
);
rollup.validateInboxConsumption(inbox, endHash, 5, SLOT, 0);
}
Expand Down
Loading