Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
06ca528
initial
Mar 4, 2024
8c14998
new
Mar 5, 2024
f6dd799
fix name
Mar 6, 2024
66b4fdd
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 6, 2024
9ddf5fe
fix
Mar 6, 2024
76091ea
Add error cases
Mar 6, 2024
d411a65
fix
Mar 7, 2024
813a592
fomrat
Mar 7, 2024
ec90ee8
slither
Mar 8, 2024
bd7c58e
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 8, 2024
6131ecf
slither
Mar 8, 2024
44ff77b
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 8, 2024
9899a93
correct slither version
Mar 8, 2024
980c711
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 9, 2024
1c1b87e
add fn selectors
Mar 9, 2024
a1b471c
Merge remote-tracking branch 'origin/master' into ek/feat/new-outbox-…
Mar 11, 2024
02f6fcd
slither
Mar 11, 2024
e964b7d
fix
Mar 11, 2024
6657587
use 8.22
Mar 11, 2024
622375c
comment
Mar 11, 2024
486dbeb
comments
Mar 11, 2024
cd89926
remove
Mar 11, 2024
2163906
format
Mar 11, 2024
b960106
lint
Mar 11, 2024
97d3497
slither
Mar 11, 2024
10ded0e
upgrade to .24
Mar 11, 2024
3ee4dad
fix
Mar 11, 2024
8393d6a
slither
Mar 11, 2024
98e9779
test
Mar 11, 2024
2580dce
new detail
Mar 12, 2024
1e1cfe4
Update l1-contracts/test/merkle/Merkle.t.sol
sklppy88 Mar 12, 2024
1d9f120
Update l1-contracts/test/merkle/Merkle.t.sol
sklppy88 Mar 12, 2024
69046ac
naming
Mar 12, 2024
e74ba1d
fix
Mar 12, 2024
7dbafcf
comments
Mar 12, 2024
0a19afa
test
Mar 12, 2024
8d6dbb3
comments
Mar 12, 2024
a08f272
asdf
Mar 12, 2024
6e114dc
fix
Mar 12, 2024
de503db
fix
Mar 12, 2024
cde4943
comments
Mar 12, 2024
a1dad25
slith
Mar 12, 2024
1e81b50
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 12, 2024
c19828a
test
Mar 12, 2024
2b8748f
Update l1-contracts/src/core/libraries/Merkle.sol
sklppy88 Mar 13, 2024
ed6398f
move out of core
Mar 13, 2024
7bd699d
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 13, 2024
03b4676
abc
Mar 13, 2024
eecf80b
format
Mar 13, 2024
3bc409b
slither
Mar 13, 2024
bd639ae
naming
Mar 13, 2024
b8ddbf8
renames
Mar 13, 2024
75b3ed1
slith
Mar 13, 2024
5c32f4f
Version update
Mar 14, 2024
8d58656
rename
Mar 14, 2024
b94bb51
comments
Mar 14, 2024
3913aa9
comments
Mar 14, 2024
4d3369d
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 14, 2024
bdc0396
Update INewOutbox.sol
sklppy88 Mar 15, 2024
7883ab6
Update l1-contracts/src/core/messagebridge/NewOutbox.sol
sklppy88 Mar 15, 2024
8103b96
Update l1-contracts/src/core/messagebridge/NewOutbox.sol
sklppy88 Mar 15, 2024
ba536ed
fix: Point docs links to current tag if available (#5219)
spalladino Mar 14, 2024
1170081
chore(docs): Add details to getting started contract deployment (#5220)
critesjosh Mar 14, 2024
afa0555
chore(master): Release 0.28.0 (#5192)
AztecBot Mar 14, 2024
1256848
fix: Docs links URL missing a letter (#5223)
spalladino Mar 14, 2024
84c24ec
chore(docs): add note on new initializer (#5224)
critesjosh Mar 14, 2024
d0dc528
fix(docs): Update other constructor refs in docs to use initializer (…
critesjosh Mar 14, 2024
9698d44
move to util
Mar 15, 2024
1735d75
test
Mar 15, 2024
aa2e3bc
slither
Mar 15, 2024
1fcd93d
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 15, 2024
9e7fc6b
Merge branch 'master' into ek/feat/new-outbox-contract
Mar 15, 2024
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
244 changes: 44 additions & 200 deletions l1-contracts/slither_output.md

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions l1-contracts/src/core/interfaces/messagebridge/INewOutbox.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Aztec Labs.
pragma solidity >=0.8.18;

import {DataStructures} from "../../libraries/DataStructures.sol";

/**
* @title INewOutbox
* @author Aztec Labs
* @notice Lives on L1 and is used to consume L2 -> L1 messages. Messages are inserted by the rollup contract
* and will be consumed by the portal contracts.
*/
// TODO: rename to IOutbox once all the pieces of the new message model are in place.
interface INewOutbox {
event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root, uint256 height);
event MessageConsumed(
uint256 indexed l2BlockNumber, bytes32 indexed root, bytes32 indexed messageHash
);

/*
* @notice Inserts the root of a merkle tree containing all of the L2 to L1 messages in
* a block specified by _blockNumber.
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
* @dev Only callable by the state transitioner (rollup contract)
* @dev Emits `RootAdded` upon inserting the root successfully
* @param _l2BlockNumber - The L2 Block Number in which the L2 to L1 messages reside
* @param _root - The merkle root of the tree where all the L2 to L1 messages are leaves
* @param _height - The height of the merkle tree that the root corresponds to
*/
function insert(uint256 _l2BlockNumber, bytes32 _root, uint256 _height) external;

/*
* @notice Consumes an entry from the Outbox
* @dev Only meaningfully callable by portals / recipients of messages
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
* @dev Emits `MessageConsumed` when consuming messages
* @param _l2BlockNumber - The block number specifying the block that contains the message we want to consume
* @param _leafIndex - The index inside the merkle tree where the message is located
* @param _message - The L2 to L1 message
* @param _path - The sibling path used to prove inclusion of the message
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
*/
function consume(
uint256 _l2BlockNumber,
uint256 _leafIndex,
DataStructures.L2ToL1Msg memory _message,
bytes32[] memory _path
) external;
}
6 changes: 6 additions & 0 deletions l1-contracts/src/core/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ library Errors {
uint32 storedDeadline,
uint32 deadlinePassed
); // 0x5e789f34
error Outbox__InvalidPathLength(uint256 expected, uint256 actual);
error Outbox__InvalidRoot(bytes32 expected, bytes32 actual);
error Outbox__RootAlreadySet(uint256 l2BlockNumber);
error Outbox__InvalidRecipient(address expected, address actual);
error Outbox__AlreadyNullified(uint256 l2BlockNumber, uint256 leafIndex);
error Outbox__NothingToConsumeAtBlock(uint256 l2BlockNumber);
Comment thread
sklppy88 marked this conversation as resolved.
Outdated

// Rollup
error Rollup__InvalidArchive(bytes32 expected, bytes32 actual); // 0xb682a40e
Expand Down
144 changes: 144 additions & 0 deletions l1-contracts/src/core/messagebridge/NewOutbox.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Aztec Labs.
pragma solidity >=0.8.18;

// Libraries
import {DataStructures} from "../libraries/DataStructures.sol";
import {Errors} from "../libraries/Errors.sol";
import {Hash} from "../libraries/Hash.sol";
import {INewOutbox} from "../interfaces/messagebridge/INewOutbox.sol";

/**
* @title NewOutbox
* @author Aztec Labs
* @notice Lives on L1 and is used to consume L2 -> L1 messages. Messages are inserted by the state transitioner

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everywhere else in solidity we call state transitioner a Rollup so would prefer to stick to that naming. I see Rollup as an implementation of the abstract "state transitioner" from yellow paper.

* and will be consumed by the portal contracts.
*/
contract NewOutbox is INewOutbox {
using Hash for DataStructures.L2ToL1Msg;

struct RootData {
bytes32 root;
uint256 height;
mapping(uint256 => bool) nullified;
}

address public immutable STATE_TRANSITIONER;
mapping(uint256 l2BlockNumber => RootData) public roots;

constructor(address _stateTransitioner) {
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
STATE_TRANSITIONER = _stateTransitioner;
}

/*
* @notice Inserts the root of a merkle tree containing all of the L2 to L1 messages in
* a block specified by _blockNumber.
* @dev Only callable by the state transitioner (rollup contract)
* @dev Emits `RootAdded` upon inserting the root successfully
* @param _l2BlockNumber - The L2 Block Number in which the L2 to L1 messages reside
* @param _root - The merkle root of the tree where all the L2 to L1 messages are leaves
* @param _height - The height of the merkle tree that the root corresponds to
*/
function insert(uint256 _l2BlockNumber, bytes32 _root, uint256 _height)
external
override(INewOutbox)
{
if (msg.sender != STATE_TRANSITIONER) {
revert Errors.Outbox__Unauthorized();
}

if (roots[_l2BlockNumber].root != bytes32(0)) {
revert Errors.Outbox__RootAlreadySet(_l2BlockNumber);
}
Comment thread
sklppy88 marked this conversation as resolved.

roots[_l2BlockNumber].root = _root;
roots[_l2BlockNumber].height = _height;

emit RootAdded(_l2BlockNumber, _root, _height);
}

/*
* @notice Consumes an entry from the Outbox
* @dev Only meaningfully callable by portals / recipients of messages
* @dev Emits `MessageConsumed` when consuming messages
* @param _l2BlockNumber - The block number specifying the block that contains the message we want to consume
* @param _leafIndex - The index inside the merkle tree where the message is located
* @param _message - The L2 to L1 message
* @param _path - The sibling path used to prove inclusion of the message
*/
function consume(
uint256 _l2BlockNumber,
uint256 _leafIndex,
DataStructures.L2ToL1Msg memory _message,
bytes32[] memory _path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that it would be better to use calldata for _message and _path given that you don't need to modify the values and calldata is cheaper.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(do benchmark and compare if you do this though)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do actually see a speedup over many runs, it may be just the test environment, but very interesting nonetheless

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a speedup that you can just see, it is evaluating the gas, you can add --gas-report to see the gas, and compare those. Think there is a new flag now to do it properly though for the exact gas but cannot remember it at the top of my head.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick snippet:
Using 256 messages of a same starting point (no fuzzing)

Memory
image

Calldata
image

) public override(INewOutbox) {
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
if (msg.sender != _message.recipient.actor) {
revert Errors.Outbox__InvalidRecipient(_message.recipient.actor, msg.sender);
}

if (block.chainid != _message.recipient.chainId) {
revert Errors.Outbox__InvalidChainId();
}

bytes32 expectedRoot = roots[_l2BlockNumber].root;
Comment thread
sklppy88 marked this conversation as resolved.
Outdated

if (expectedRoot == 0) {
revert Errors.Outbox__NothingToConsumeAtBlock(_l2BlockNumber);
}

if (roots[_l2BlockNumber].nullified[_leafIndex]) {
revert Errors.Outbox__AlreadyNullified(_l2BlockNumber, _leafIndex);
}

uint256 expectedHeight = roots[_l2BlockNumber].height;

if (expectedHeight != _path.length) {
revert Errors.Outbox__InvalidPathLength(expectedHeight, _path.length);
}

bytes32 messageHash = _verifyMembership(_path, _message, _leafIndex, expectedRoot);
Comment thread
sklppy88 marked this conversation as resolved.
Outdated

roots[_l2BlockNumber].nullified[_leafIndex] = true;

emit MessageConsumed(_l2BlockNumber, expectedRoot, messageHash);
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
}

/*
* @notice Verifies the membership of an L2 to L1 message against an expected root.
* @dev This function assumes a valid path height, as well as sane inputs.
* @dev In the case of a mismatched root, and subsequent inability to verify membership, this function throws
* and does not return anything.
* @param _path - The sibling path of the message as a leaf, used to prove message inclusion
* @param _message - The message we are trying to prove inclusion for
* @param _index - The index of the message inside the L2 to L1 message tree
* @param _expectedRoot - The expected root to check the validity of the message and sibling path with.
* @returns - The leaf of the message in the L2 to L1 tree, which is the L2 to L1 message hashed via SHA256.
*/
function _verifyMembership(
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
bytes32[] memory _path,
DataStructures.L2ToL1Msg memory _message,
uint256 _index,
bytes32 _expectedRoot
) internal pure returns (bytes32) {
bytes32 leaf = _message.sha256ToField();

bytes32 root;
uint256 index = _index;
Comment thread
sklppy88 marked this conversation as resolved.
Outdated

for (uint256 i = 0; i < _path.length; i++) {
bool isRight = (index & 1) == 1;

root = isRight
? sha256(bytes.concat(_path[i], i == 0 ? leaf : root))
Comment thread
sklppy88 marked this conversation as resolved.
Outdated
: sha256(bytes.concat(i == 0 ? leaf : root, _path[i]));

index /= 2;
}

if (root != _expectedRoot) {
revert Errors.Outbox__InvalidRoot(_expectedRoot, root);
}

return leaf;
}
}
Loading