forked from visoftsolutions/noir_rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add data availability oracle (AztecProtocol#3897)
Fixes AztecProtocol#3890
- Loading branch information
Showing
9 changed files
with
600 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
l1-contracts/src/core/availability_oracle/AvailabilityOracle.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Aztec Labs. | ||
pragma solidity >=0.8.18; | ||
|
||
// Interfaces | ||
import {IAvailabilityOracle} from "./../interfaces/IAvailabilityOracle.sol"; | ||
|
||
// Libraries | ||
import {TxsDecoder} from "./../libraries/decoders/TxsDecoder.sol"; | ||
|
||
/** | ||
* @title AvailabilityOracle | ||
* @author Aztec Labs | ||
* @notice An availability oracle that uses L1 calldata for publication | ||
*/ | ||
contract AvailabilityOracle is IAvailabilityOracle { | ||
mapping(bytes32 txsHash => bool available) public override(IAvailabilityOracle) isAvailable; | ||
|
||
/** | ||
* @notice Publishes transactions and marks its commitment, the TxsHash, as available | ||
* @param _body - The L1 calldata | ||
* @return txsHash - The TxsHash | ||
*/ | ||
function publish(bytes calldata _body) external override(IAvailabilityOracle) returns (bytes32) { | ||
bytes32 _txsHash = TxsDecoder.decode(_body); | ||
isAvailable[_txsHash] = true; | ||
return _txsHash; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Aztec Labs. | ||
pragma solidity >=0.8.18; | ||
|
||
interface IAvailabilityOracle { | ||
function publish(bytes calldata _body) external returns (bytes32); | ||
|
||
function isAvailable(bytes32 _txsHash) external view returns (bool); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
l1-contracts/src/core/libraries/decoders/HeaderDecoder.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2023 Aztec Labs. | ||
pragma solidity >=0.8.18; | ||
|
||
// Libraries | ||
import {Constants} from "../ConstantsGen.sol"; | ||
import {Hash} from "../Hash.sol"; | ||
|
||
/** | ||
* @title Header Decoder Library | ||
* @author Aztec Labs | ||
* @notice Decoding a L2 header | ||
* Concerned with readability and velocity of development not giving a damn about gas costs. | ||
* | ||
* ------------------- | ||
* You can use https://gist.github.com/LHerskind/724a7e362c97e8ac2902c6b961d36830 to generate the below outline. | ||
* ------------------- | ||
* L2 Block Header specification | ||
* ------------------- | ||
* | ||
* | byte start | num bytes | name | ||
* | --- | --- | --- | ||
* | 0x0000 | 0x20 | chain-id | ||
* | 0x0020 | 0x20 | version | ||
* | 0x0040 | 0x20 | L2 block number | ||
* | 0x0060 | 0x20 | L2 timestamp | ||
* | 0x0080 | 0x20 | startNoteHashTreeSnapshot.root | ||
* | 0x00a0 | 0x04 | startNoteHashTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x00a4 | 0x20 | startNullifierTreeSnapshot.root | ||
* | 0x00c4 | 0x04 | startNullifierTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x00c8 | 0x20 | startContractTreeSnapshot.root | ||
* | 0x00e8 | 0x04 | startContractTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x00ec | 0x20 | startPublicDataTreeSnapshot.root | ||
* | 0x010c | 0x04 | startPublicDataTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x0110 | 0x20 | startL1ToL2MessageTreeSnapshot.root | ||
* | 0x0130 | 0x04 | startL1ToL2MessageTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x0134 | 0x20 | startArchiveSnapshot.root | ||
* | 0x0154 | 0x04 | startArchiveSnapshot.nextAvailableLeafIndex | ||
* | 0x0158 | 0x20 | endNoteHashTreeSnapshot.root | ||
* | 0x0178 | 0x04 | endNoteHashTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x017c | 0x20 | endNullifierTreeSnapshot.root | ||
* | 0x019c | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x01a0 | 0x20 | endContractTreeSnapshot.root | ||
* | 0x01c0 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x01c4 | 0x20 | endPublicDataTreeSnapshot.root | ||
* | 0x01e4 | 0x04 | endPublicDataTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x01e8 | 0x20 | endL1ToL2MessageTreeSnapshot.root | ||
* | 0x0208 | 0x04 | endL1ToL2MessageTreeSnapshot.nextAvailableLeafIndex | ||
* | 0x020c | 0x20 | endArchiveSnapshot.root | ||
* | 0x022c | 0x04 | endArchiveSnapshot.nextAvailableLeafIndex | ||
* | --- | --- | --- | ||
*/ | ||
library HeaderDecoder { | ||
// DECODING OFFSET CONSTANTS | ||
// Where the start of trees metadata begins in the block | ||
uint256 private constant START_TREES_BLOCK_HEADER_OFFSET = 0x80; | ||
|
||
// The size of the block header elements | ||
uint256 private constant TREES_BLOCK_HEADER_SIZE = 0xd8; | ||
|
||
// Where the end of trees metadata begins in the block | ||
uint256 private constant END_TREES_BLOCK_HEADER_OFFSET = | ||
START_TREES_BLOCK_HEADER_OFFSET + TREES_BLOCK_HEADER_SIZE; | ||
|
||
// Where the metadata ends and the block data begins. | ||
uint256 internal constant BLOCK_HEADER_SIZE = | ||
START_TREES_BLOCK_HEADER_OFFSET + 2 * TREES_BLOCK_HEADER_SIZE; | ||
|
||
/** | ||
* @notice Decodes the header | ||
* @param _header - The L2 block calldata. | ||
* @return l2BlockNumber - The L2 block number | ||
* @return startStateHash - The start state hash | ||
* @return endStateHash - The end state hash | ||
*/ | ||
function decode(bytes calldata _header) | ||
internal | ||
pure | ||
returns (uint256 l2BlockNumber, bytes32 startStateHash, bytes32 endStateHash) | ||
{ | ||
l2BlockNumber = uint256(bytes32(_header[0x40:0x60])); | ||
// Note, for startStateHash to match the storage, the l2 block number must be new - 1. | ||
// Only jumping 1 block at a time. | ||
startStateHash = computeStateHash(l2BlockNumber - 1, START_TREES_BLOCK_HEADER_OFFSET, _header); | ||
endStateHash = computeStateHash(l2BlockNumber, END_TREES_BLOCK_HEADER_OFFSET, _header); | ||
} | ||
|
||
/** | ||
* @notice Computes a state hash | ||
* @param _l2BlockNumber - The L2 block number | ||
* @param _offset - The offset into the data, 0x80 for start, 0x019c for end | ||
* @param _header - The L2 block calldata. | ||
* @return The state hash | ||
* @dev The state hash is sha256 hash of block's header elements. For each block the header elements are | ||
* the block number, snapshots of all the trees and the root of the public data tree. This function | ||
* copies all of these to memory and then hashes them. | ||
*/ | ||
function computeStateHash(uint256 _l2BlockNumber, uint256 _offset, bytes calldata _header) | ||
internal | ||
pure | ||
returns (bytes32) | ||
{ | ||
return sha256( | ||
bytes.concat(bytes32(_l2BlockNumber), _header[_offset:_offset + TREES_BLOCK_HEADER_SIZE]) | ||
); | ||
} | ||
} |
109 changes: 109 additions & 0 deletions
109
l1-contracts/src/core/libraries/decoders/MessagesDecoder.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Aztec Labs. | ||
pragma solidity >=0.8.18; | ||
|
||
// Libraries | ||
import {Constants} from "../ConstantsGen.sol"; | ||
import {Hash} from "../Hash.sol"; | ||
|
||
/** | ||
* @title Messages Decoder Library | ||
* @author Aztec Labs | ||
* @notice Decoding a L2 block body and returns cross-chain messages + (in/out)Hash. | ||
* Concerned with readability and velocity of development not giving a damn about gas costs. | ||
* @dev Assumes the input trees to be padded. | ||
* | ||
* ------------------- | ||
* You can use https://gist.github.com/LHerskind/724a7e362c97e8ac2902c6b961d36830 to generate the below outline. | ||
* ------------------- | ||
* L2 Body Data specification | ||
* ------------------- | ||
* | ||
* | byte start | num bytes | name | ||
* | --- | --- | --- | ||
* | 0x00 | 0x04 | len(newCommitments) (denoted a) | ||
* | 0x04 | a * 0x20 | newCommitments | ||
* | 0x04 + a * 0x20 | 0x04 | len(newNullifiers) (denoted b) | ||
* | 0x08 + a * 0x20 | b * 0x20 | newNullifiers | ||
* | 0x08 + a * 0x20 + b * 0x20 | 0x04 | len(newPublicDataWrites) (denoted c) | ||
* | 0x0c + a * 0x20 + b * 0x20 | c * 0x40 | newPublicDataWrites | ||
* | 0x0c + a * 0x20 + b * 0x20 + c * 0x40 | 0x04 | len(newL2ToL1Msgs) (denoted d) | ||
* | 0x10 + a * 0x20 + b * 0x20 + c * 0x40 | d * 0x20 | newL2ToL1Msgs | ||
* | 0x10 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 | 0x04 | len(contracts) (denoted e) | ||
* | 0x14 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 | e * 0x20 | newContracts | ||
* | 0x14 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x20 | e * 0x34 | newContractsData | ||
* | 0x14 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 | 0x04 | len(newL1ToL2Msgs) (denoted f) | ||
* | 0x18 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 | f * 0x20 | newL1ToL2Msgs | ||
* | 0x18 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 + f * 0x20 | 0x04 | byteLen(newEncryptedLogs) (denoted g) | ||
* | 0x1c + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 + f * 0x20 | g | newEncryptedLogs | ||
* | 0x1c + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 + f * 0x20 + g | 0x04 | byteLen(newUnencryptedLogs) (denoted h) | ||
* | 0x20 + a * 0x20 + b * 0x20 + c * 0x40 + d * 0x20 + e * 0x54 + f * 0x20 + g | h | newUnencryptedLogs | ||
* | --- | --- | --- | ||
*/ | ||
library MessagesDecoder { | ||
/** | ||
* @notice Computes consumables for the block | ||
* @param _body - The L2 block calldata. | ||
* @return l1ToL2MsgsHash - The hash of the L1 to L2 messages | ||
* @return l2ToL1MsgsHash - The hash of the L1 to L2 messages | ||
* @return l2ToL1Msgs - The L2 to L1 messages of the block | ||
* @return l1ToL2Msgs - The L1 to L2 messages of the block | ||
*/ | ||
function decode(bytes calldata _body) | ||
internal | ||
pure | ||
returns (bytes32, bytes32, bytes32[] memory, bytes32[] memory) | ||
{ | ||
bytes32[] memory l1ToL2Msgs = new bytes32[](Constants.NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); | ||
bytes32[] memory l2ToL1Msgs; | ||
|
||
uint256 offset = 0; | ||
|
||
// Commitments | ||
uint256 count = read4(_body, offset); | ||
offset += 0x4 + count * 0x20; | ||
|
||
// Nullifiers | ||
count = read4(_body, offset); | ||
offset += 0x4 + count * 0x20; | ||
|
||
// Public data writes | ||
count = read4(_body, offset); | ||
offset += 0x4 + count * 0x40; | ||
|
||
// L2 to L1 messages | ||
count = read4(_body, offset); | ||
l2ToL1Msgs = new bytes32[](count); | ||
assembly { | ||
calldatacopy(add(l2ToL1Msgs, 0x20), add(_body.offset, add(offset, 0x4)), mul(count, 0x20)) | ||
} | ||
offset += 0x4 + count * 0x20; | ||
|
||
// Contracts | ||
count = read4(_body, offset); | ||
offset += 0x4 + count * 0x54; | ||
|
||
// L1 to L2 messages | ||
count = read4(_body, offset); | ||
// `l1ToL2Msgs` is fixed size so if `lengths.l1Tol2MsgsCount` < `Constants.NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP` the array | ||
// will contain some zero values. | ||
assembly { | ||
calldatacopy(add(l1ToL2Msgs, 0x20), add(_body.offset, add(offset, 0x04)), mul(count, 0x20)) | ||
} | ||
|
||
bytes32 l1ToL2MsgsHash = sha256(abi.encodePacked(l1ToL2Msgs)); | ||
bytes32 l2ToL1MsgsHash = sha256(abi.encodePacked(l2ToL1Msgs)); | ||
|
||
return (l1ToL2MsgsHash, l2ToL1MsgsHash, l2ToL1Msgs, l1ToL2Msgs); | ||
} | ||
|
||
/** | ||
* @notice Reads 4 bytes from the data | ||
* @param _data - The data to read from | ||
* @param _offset - The offset to read from | ||
* @return The 4 bytes read as a uint256 | ||
*/ | ||
function read4(bytes calldata _data, uint256 _offset) internal pure returns (uint256) { | ||
return uint256(uint32(bytes4(_data[_offset:_offset + 4]))); | ||
} | ||
} |
Oops, something went wrong.