From 3ddc485e94debf183754f6c653f40fc9402f8638 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 29 Apr 2025 15:57:22 +0000 Subject: [PATCH] Remove unneeded root rollup public inputs. --- l1-contracts/src/core/interfaces/IRollup.sol | 2 - .../src/core/libraries/ConstantsGen.sol | 2 +- .../core/libraries/rollup/EpochProofLib.sol | 30 ++-------- l1-contracts/test/Rollup.t.sol | 11 +--- l1-contracts/test/base/RollupBase.sol | 2 - l1-contracts/test/benchmark/happy.t.sol | 2 - l1-contracts/test/fees/FeeRollup.t.sol | 2 - .../block_merge/block_merge_rollup_inputs.nr | 14 +---- .../crates/rollup-lib/src/components.nr | 29 +-------- .../crates/rollup-lib/src/root/mod.nr | 60 ++++++++++--------- .../rollup-lib/src/root/root_rollup_inputs.nr | 18 +++--- .../src/root/root_rollup_public_inputs.nr | 8 +-- .../src/tests/previous_rollup_block_data.nr | 5 ++ .../crates/types/src/constants.nr | 7 +-- yarn-project/constants/src/constants.gen.ts | 2 +- yarn-project/ethereum/src/contracts/rollup.ts | 2 - .../src/conversion/server.ts | 7 +-- .../orchestrator_multiple_blocks.test.ts | 19 ++++-- .../src/prover-node-publisher.test.ts | 6 +- .../prover-node/src/prover-node-publisher.ts | 14 ++--- yarn-project/stdlib/src/rollup/root_rollup.ts | 25 ++------ yarn-project/stdlib/src/tests/factories.ts | 11 ++-- 22 files changed, 100 insertions(+), 178 deletions(-) diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index d6aae2158955..9b4f66bbb059 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -19,8 +19,6 @@ import {IERC20} from "@oz/token/ERC20/IERC20.sol"; struct PublicInputArgs { bytes32 previousArchive; bytes32 endArchive; - Timestamp endTimestamp; - bytes32 outHash; address proverId; } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 520220c70aad..7b48f9df492e 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -217,7 +217,7 @@ library Constants { uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 52; uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 1032; - uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 1020; + uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 1015; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/l1-contracts/src/core/libraries/rollup/EpochProofLib.sol b/l1-contracts/src/core/libraries/rollup/EpochProofLib.sol index ae9767563411..ef19eeb5baba 100644 --- a/l1-contracts/src/core/libraries/rollup/EpochProofLib.sol +++ b/l1-contracts/src/core/libraries/rollup/EpochProofLib.sol @@ -143,11 +143,8 @@ library EpochProofLib { // Structure of the root rollup public inputs we need to reassemble: // // struct RootRollupPublicInputs { - // previous_archive: AppendOnlyTreeSnapshot, - // end_archive: AppendOnlyTreeSnapshot, - // end_timestamp: u64, - // end_block_number: Field, - // out_hash: Field, + // previous_archive_root: Field, + // end_archive_root: Field, // proposedBlockHeaderHashes: [Field; Constants.AZTEC_MAX_EPOCH_DURATION], // fees: [FeeRecipient; Constants.AZTEC_MAX_EPOCH_DURATION], // chain_id: Field, @@ -161,34 +158,17 @@ library EpochProofLib { // previous_archive.root: the previous archive tree root publicInputs[0] = _args.previousArchive; - // previous_archive.next_available_leaf_index: the previous archive next available index - // normally this should be equal to the block number (since leaves are 0-indexed and blocks 1-indexed) - // but in yarn-project/merkle-tree/src/new_tree.ts we prefill the tree so that block N is in leaf N - publicInputs[1] = bytes32(_start); - // end_archive.root: the new archive tree root - publicInputs[2] = _args.endArchive; - - // end_archive.next_available_leaf_index: the new archive next available index - publicInputs[3] = bytes32(_end + 1); - - // end_timestamp: the timestamp of the last block in the epoch - publicInputs[4] = bytes32(Timestamp.unwrap(_args.endTimestamp)); - - // end_block_number: last block number in the epoch - publicInputs[5] = bytes32(_end); - - // out_hash: root of this epoch's l2 to l1 message tree - publicInputs[6] = _args.outHash; + publicInputs[1] = _args.endArchive; } uint256 numBlocks = _end - _start + 1; for (uint256 i = 0; i < numBlocks; i++) { - publicInputs[7 + i] = rollupStore.blocks[_start + i].headerHash; + publicInputs[2 + i] = rollupStore.blocks[_start + i].headerHash; } - uint256 offset = 7 + Constants.AZTEC_MAX_EPOCH_DURATION; + uint256 offset = 2 + Constants.AZTEC_MAX_EPOCH_DURATION; uint256 feesLength = Constants.AZTEC_MAX_EPOCH_DURATION * 2; // fees[2n to 2n + 1]: a fee element, which contains of a recipient and a value diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 864420b19e99..20a08889b74b 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -567,8 +567,6 @@ contract RollupTest is RollupBase { PublicInputArgs memory args = PublicInputArgs({ previousArchive: blockLog.archive, endArchive: data.archive, - endTimestamp: Timestamp.wrap(0), - outHash: bytes32(0), proverId: address(0) }); @@ -760,13 +758,8 @@ contract RollupTest is RollupBase { address _coinbase, uint256 _fee ) internal { - PublicInputArgs memory args = PublicInputArgs({ - previousArchive: _prevArchive, - endArchive: _archive, - endTimestamp: Timestamp.wrap(0), - outHash: bytes32(0), - proverId: _prover - }); + PublicInputArgs memory args = + PublicInputArgs({previousArchive: _prevArchive, endArchive: _archive, proverId: _prover}); bytes32[] memory fees = new bytes32[](Constants.AZTEC_MAX_EPOCH_DURATION * 2); fees[0] = bytes32(uint256(uint160(bytes20(_coinbase)))); // Need the address to be left padded within the bytes32 diff --git a/l1-contracts/test/base/RollupBase.sol b/l1-contracts/test/base/RollupBase.sol index e04699ae9cf4..1ed601d5595c 100644 --- a/l1-contracts/test/base/RollupBase.sol +++ b/l1-contracts/test/base/RollupBase.sol @@ -71,8 +71,6 @@ contract RollupBase is DecoderBase { PublicInputArgs memory args = PublicInputArgs({ previousArchive: parentBlockLog.archive, endArchive: endFull.block.archive, - endTimestamp: Timestamp.wrap(0), // WHAT ? - outHash: bytes32(0), // WHAT ? proverId: _prover }); diff --git a/l1-contracts/test/benchmark/happy.t.sol b/l1-contracts/test/benchmark/happy.t.sol index 5f423d6370e2..0333d6c26ce8 100644 --- a/l1-contracts/test/benchmark/happy.t.sol +++ b/l1-contracts/test/benchmark/happy.t.sol @@ -360,8 +360,6 @@ contract BenchmarkRollupTest is FeeModelTestPoints, DecoderBase { PublicInputArgs memory args = PublicInputArgs({ previousArchive: rollup.getBlock(start).archive, endArchive: rollup.getBlock(start + epochSize - 1).archive, - endTimestamp: Timestamp.wrap(0), - outHash: bytes32(0), proverId: address(0) }); diff --git a/l1-contracts/test/fees/FeeRollup.t.sol b/l1-contracts/test/fees/FeeRollup.t.sol index 3862be1f56da..b334e16c7155 100644 --- a/l1-contracts/test/fees/FeeRollup.t.sol +++ b/l1-contracts/test/fees/FeeRollup.t.sol @@ -416,8 +416,6 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase { PublicInputArgs memory args = PublicInputArgs({ previousArchive: rollup.getBlock(start).archive, endArchive: rollup.getBlock(start + epochSize - 1).archive, - endTimestamp: Timestamp.wrap(0), - outHash: bytes32(0), proverId: address(0) }); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr index 4ea43df93e54..f604a6e68573 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr @@ -49,8 +49,6 @@ impl BlockMergeRollupInputs { // ^ Where instead of num_txs, use num_blocks = (end_global_variables.block_number - start_global_variables.block_number) + 1 components::assert_prev_block_rollups_follow_on_from_each_other(left, right); - let out_hash = components::compute_blocks_out_hash(self.previous_rollup_data); - let proposed_block_header_hashes = components::accumulate_proposed_block_header_hashes(left, right); @@ -67,7 +65,7 @@ impl BlockMergeRollupInputs { new_archive: right.new_archive, start_global_variables: left.start_global_variables, end_global_variables: right.end_global_variables, - out_hash, + out_hash: 0, // Not needed for block merge. This is only required for block root since the value is inserted on L1 per block. proposed_block_header_hashes, fees, vk_tree_root: left.vk_tree_root, @@ -83,7 +81,6 @@ mod tests { use dep::types::constants::{ BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_INDEX, ROOT_PARITY_INDEX, }; - use dep::types::hash::accumulate_sha256; use dep::types::tests::fixtures; use types::merkle_tree::merkle_tree::MerkleTree; @@ -122,15 +119,6 @@ mod tests { let _output = inputs.block_merge_rollup_circuit(); } - #[test] - fn out_hash() { - let mut inputs = default_block_merge_rollup_inputs(); - let expected_hash = accumulate_sha256([1, 2]); - let outputs = inputs.block_merge_rollup_circuit(); - - assert_eq(outputs.out_hash, expected_hash); - } - #[test] fn block_fees_are_accumulated() { let mut inputs = default_block_merge_rollup_inputs(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 3e8b1963b52d..68e80f925394 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -1,6 +1,5 @@ -use crate::abis::{ - block_root_or_block_merge_public_inputs::{BlockRootOrBlockMergePublicInputs, FeeRecipient}, - previous_rollup_block_data::PreviousRollupBlockData, +use crate::abis::block_root_or_block_merge_public_inputs::{ + BlockRootOrBlockMergePublicInputs, FeeRecipient, }; use super::abis::tx_effect::TxEffect; use dep::types::{ @@ -18,7 +17,7 @@ use dep::types::{ PUBLIC_LOG_SIZE_IN_FIELDS, PUBLIC_LOGS_PREFIX, REVERT_CODE_PREFIX, TX_FEE_PREFIX, TX_START_PREFIX, }, - hash::{accumulate_sha256, compute_contract_class_log_hash}, + hash::compute_contract_class_log_hash, merkle_tree::VariableMerkleTree, traits::{Empty, Serialize, ToField}, utils::arrays::{array_length, array_merge, padded_array_length, unsafe_padded_array_length}, @@ -82,12 +81,6 @@ pub fn accumulate_blocks_fees( left: BlockRootOrBlockMergePublicInputs, right: BlockRootOrBlockMergePublicInputs, ) -> [FeeRecipient; AZTEC_MAX_EPOCH_DURATION] { - let left_len = array_length(left.fees); - let right_len = array_length(right.fees); - assert( - left_len + right_len <= AZTEC_MAX_EPOCH_DURATION, - "too many fee payment structs accumulated in rollup", - ); // TODO(Miranda): combine fees with same recipient depending on rollup structure // Assuming that the final rollup tree (block root -> block merge -> root) has max 32 leaves (TODO: constrain in root), then // in the worst case, we would be checking the left 16 values (left_len = 16) against the right 16 (right_len = 16). @@ -102,11 +95,6 @@ pub fn accumulate_blob_public_inputs( right: BlockRootOrBlockMergePublicInputs, ) -> [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION] { let left_len = array_length(left.blob_public_inputs); - let right_len = array_length(right.blob_public_inputs); - assert( - left_len + right_len <= AZTEC_MAX_EPOCH_DURATION, - "too many blob public input structs accumulated in rollup", - ); // NB: The below is cheaper than array_merge because assigning BlockBlobPublicInputs is cheaper than calling .equals let mut add_from_left = true; let mut result = [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; @@ -121,17 +109,6 @@ pub fn accumulate_blob_public_inputs( result } -pub fn compute_blocks_out_hash(previous_rollup_data: [PreviousRollupBlockData; 2]) -> Field { - if previous_rollup_data[1].block_root_or_block_merge_public_inputs.is_padding() { - previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash - } else { - accumulate_sha256([ - previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash, - previous_rollup_data[1].block_root_or_block_merge_public_inputs.out_hash, - ]) - } -} - pub fn compute_kernel_out_hash(l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX]) -> Field { let non_empty_items = array_length(l2_to_l1_msgs); let merkle_tree = VariableMerkleTree::new_sha(l2_to_l1_msgs, non_empty_items); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr index d1af19e63a54..72d664b7c1b2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr @@ -7,39 +7,45 @@ pub use root_rollup_public_inputs::RootRollupPublicInputs; mod tests { use crate::tests::root_rollup_inputs::default_root_rollup_inputs; - use dep::types::hash::accumulate_sha256; + use dep::types::tests::utils::assert_array_eq; #[test] - fn check_block_hashes_empty_blocks() { - let expected_out_hash = accumulate_sha256([1, 2]); - + fn root_rollup_end_state() { let inputs = default_root_rollup_inputs(); let outputs = inputs.root_rollup_circuit(); - // check out hash - assert_eq(outputs.out_hash, expected_out_hash); - } + let left = inputs.previous_rollup_data[0].block_root_or_block_merge_public_inputs; + let right = inputs.previous_rollup_data[1].block_root_or_block_merge_public_inputs; - #[test] - fn end_state() { - let inputs = default_root_rollup_inputs(); - let outputs = inputs.root_rollup_circuit(); + assert_eq(outputs.previous_archive_root, left.previous_archive.root); + + assert_eq(outputs.end_archive_root, right.new_archive.root); + + assert_array_eq( + outputs.proposed_block_header_hashes, + [left.proposed_block_header_hashes[0], right.proposed_block_header_hashes[0]], + ); + + assert_array_eq(outputs.fees, [left.fees[0], right.fees[0]]); + + assert_eq(outputs.chain_id, left.start_global_variables.chain_id); + assert_eq(outputs.chain_id, right.end_global_variables.chain_id); + + assert_eq(outputs.version, left.start_global_variables.version); + assert_eq(outputs.version, right.end_global_variables.version); + + assert_eq(outputs.vk_tree_root, left.vk_tree_root); + assert_eq(outputs.vk_tree_root, right.vk_tree_root); + + assert_eq(outputs.protocol_contract_tree_root, left.protocol_contract_tree_root); + assert_eq(outputs.protocol_contract_tree_root, right.protocol_contract_tree_root); + + assert_eq(outputs.prover_id, left.prover_id); + assert_eq(outputs.prover_id, right.prover_id); - assert(outputs.previous_archive.eq( - inputs.previous_rollup_data[0] - .block_root_or_block_merge_public_inputs - .previous_archive, - )); - - assert(outputs.end_archive.eq( - inputs.previous_rollup_data[1].block_root_or_block_merge_public_inputs.new_archive, - )); - - assert(outputs.end_timestamp.eq( - inputs.previous_rollup_data[1] - .block_root_or_block_merge_public_inputs - .end_global_variables - .timestamp, - )); + assert_array_eq( + outputs.blob_public_inputs, + [left.blob_public_inputs[0], right.blob_public_inputs[0]], + ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 7f0682bbae7c..45cb9e1a11c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -4,8 +4,8 @@ use crate::{ }; use types::{ constants::{ - BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, BLOCK_ROOT_ROLLUP_INDEX, - BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, PROOF_TYPE_ROOT_ROLLUP_HONK, + AZTEC_MAX_EPOCH_DURATION, BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, + BLOCK_ROOT_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, PROOF_TYPE_ROOT_ROLLUP_HONK, }, traits::Empty, }; @@ -54,7 +54,12 @@ impl RootRollupInputs { // ^ Where instead of num_txs, use num_blocks = (end_global_variables.block_number - start_global_variables.block_number) + 1 components::assert_prev_block_rollups_follow_on_from_each_other(left, right); - let out_hash = components::compute_blocks_out_hash(self.previous_rollup_data); + // Make sure that the total number of blocks in the epoch does not exceed the max, preventing the accumulated + // data below (proposed_block_header_hashes, fees, blob_public_inputs) from being truncated. + let num_blocks = (right.end_global_variables.block_number as u32) + - (left.start_global_variables.block_number as u32) + + 1; + assert(num_blocks <= AZTEC_MAX_EPOCH_DURATION, "too many blocks in root rollup"); let proposed_block_header_hashes = components::accumulate_proposed_block_header_hashes(left, right); @@ -68,11 +73,8 @@ impl RootRollupInputs { let blob_public_inputs = components::accumulate_blob_public_inputs(left, right); RootRollupPublicInputs { - previous_archive: left.previous_archive, - end_archive: right.new_archive, - end_timestamp: right.end_global_variables.timestamp, - end_block_number: right.end_global_variables.block_number, - out_hash, + previous_archive_root: left.previous_archive.root, + end_archive_root: right.new_archive.root, proposed_block_header_hashes, fees, chain_id: right.end_global_variables.chain_id, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr index 1c59b135a69e..22c487ea9aab 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr @@ -1,15 +1,11 @@ use crate::abis::block_root_or_block_merge_public_inputs::FeeRecipient; -use dep::types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot; use dep::types::constants::AZTEC_MAX_EPOCH_DURATION; use blob::blob_public_inputs::BlockBlobPublicInputs; pub struct RootRollupPublicInputs { // Snapshot of archive tree before/after this rollup has been processed - pub previous_archive: AppendOnlyTreeSnapshot, - pub end_archive: AppendOnlyTreeSnapshot, - pub end_timestamp: u64, - pub end_block_number: Field, - pub out_hash: Field, + pub previous_archive_root: Field, + pub end_archive_root: Field, pub proposed_block_header_hashes: [Field; AZTEC_MAX_EPOCH_DURATION], pub fees: [FeeRecipient; AZTEC_MAX_EPOCH_DURATION], pub chain_id: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr index 565e50e1ba31..25868c49a74f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr @@ -49,6 +49,11 @@ pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash = 1; previous_rollup_data[1].block_root_or_block_merge_public_inputs.out_hash = 2; + previous_rollup_data[0].block_root_or_block_merge_public_inputs.proposed_block_header_hashes[0] = + 21; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.proposed_block_header_hashes[0] = + 37; + previous_rollup_data[0].block_root_or_block_merge_public_inputs.fees[0].value = 10; previous_rollup_data[1].block_root_or_block_merge_public_inputs.fees[0].value = 15; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 347167dc46ee..57883e13d061 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -455,11 +455,8 @@ pub global BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH: u32 = 2 + 1 /* protocol_contract_tree_root */ + 1 /* prover_id */ + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK; -pub global ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH /* previous_archive */ - + APPEND_ONLY_TREE_SNAPSHOT_LENGTH /* end_archive */ - + 1 /* end_timestamp */ - + 1 /* end_block_number */ - + 1 /* out_hash */ +pub global ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH: u32 = 1 /* previous_archive_root */ + + 1 /* end_archive_root */ + 1 /* chain_id */ + 1 /* version */ + 1 /* vk_tree_root */ diff --git a/yarn-project/constants/src/constants.gen.ts b/yarn-project/constants/src/constants.gen.ts index 2ee21d558ddf..9ec8cbead94c 100644 --- a/yarn-project/constants/src/constants.gen.ts +++ b/yarn-project/constants/src/constants.gen.ts @@ -197,7 +197,7 @@ export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1026; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 52; export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 1032; -export const ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 1020; +export const ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 1015; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/ethereum/src/contracts/rollup.ts b/yarn-project/ethereum/src/contracts/rollup.ts index a5ae2e928194..cb479ec52c3f 100644 --- a/yarn-project/ethereum/src/contracts/rollup.ts +++ b/yarn-project/ethereum/src/contracts/rollup.ts @@ -30,8 +30,6 @@ export type L1RollupContractAddresses = Pick< export type EpochProofPublicInputArgs = { previousArchive: `0x${string}`; endArchive: `0x${string}`; - endTimestamp: bigint; - outHash: `0x${string}`; proverId: `0x${string}`; }; diff --git a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts index 6ff2f8c3bde0..a46372665019 100644 --- a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts +++ b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts @@ -428,11 +428,8 @@ export function mapRootRollupPublicInputsFromNoir( rootRollupPublicInputs: RootRollupPublicInputsNoir, ): RootRollupPublicInputs { return new RootRollupPublicInputs( - mapAppendOnlyTreeSnapshotFromNoir(rootRollupPublicInputs.previous_archive), - mapAppendOnlyTreeSnapshotFromNoir(rootRollupPublicInputs.end_archive), - mapFieldFromNoir(rootRollupPublicInputs.end_timestamp), - mapFieldFromNoir(rootRollupPublicInputs.end_block_number), - mapFieldFromNoir(rootRollupPublicInputs.out_hash), + mapFieldFromNoir(rootRollupPublicInputs.previous_archive_root), + mapFieldFromNoir(rootRollupPublicInputs.end_archive_root), mapTupleFromNoir(rootRollupPublicInputs.proposed_block_header_hashes, AZTEC_MAX_EPOCH_DURATION, mapFieldFromNoir), mapTupleFromNoir(rootRollupPublicInputs.fees, AZTEC_MAX_EPOCH_DURATION, mapFeeRecipientFromNoir), mapFieldFromNoir(rootRollupPublicInputs.chain_id), diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts index 68c89bfcf141..3e2e1335888a 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts @@ -1,4 +1,5 @@ import { timesAsync } from '@aztec/foundation/collection'; +import type { Fr } from '@aztec/foundation/fields'; import { createLogger } from '@aztec/foundation/log'; import { TestContext } from '../mocks/test_context.js'; @@ -10,6 +11,9 @@ const LONG_TIMEOUT = 600_000; describe('prover/orchestrator/multi-block', () => { let context: TestContext; + const countProposedBlocks = (proposedBlockHeaderHashes: Fr[]) => + proposedBlockHeaderHashes.findIndex(h => h.isEmpty()); + beforeEach(async () => { context = await TestContext.new(logger); context.orchestrator.isVerifyBuiltBlockAgainstSyncedStateEnabled = true; @@ -40,7 +44,7 @@ describe('prover/orchestrator/multi-block', () => { logger.info('Finalising epoch'); const epoch = await context.orchestrator.finaliseEpoch(); - expect(epoch.publicInputs.endBlockNumber.toNumber()).toEqual(numBlocks); + expect(countProposedBlocks(epoch.publicInputs.proposedBlockHeaderHashes)).toEqual(numBlocks); expect(epoch.proof).toBeDefined(); }); @@ -67,7 +71,7 @@ describe('prover/orchestrator/multi-block', () => { logger.info('Finalising epoch'); const epoch = await context.orchestrator.finaliseEpoch(); - expect(epoch.publicInputs.endBlockNumber.toNumber()).toEqual(numBlocks); + expect(countProposedBlocks(epoch.publicInputs.proposedBlockHeaderHashes)).toEqual(numBlocks); expect(epoch.proof).toBeDefined(); }, LONG_TIMEOUT, @@ -96,7 +100,7 @@ describe('prover/orchestrator/multi-block', () => { logger.info('Finalising epoch'); const epoch = await context.orchestrator.finaliseEpoch(); - expect(epoch.publicInputs.endBlockNumber.toNumber()).toEqual(numBlocks); + expect(countProposedBlocks(epoch.publicInputs.proposedBlockHeaderHashes)).toEqual(numBlocks); expect(epoch.proof).toBeDefined(); }, LONG_TIMEOUT, @@ -114,8 +118,9 @@ describe('prover/orchestrator/multi-block', () => { for (let epochIndex = 0; epochIndex < numEpochs; epochIndex++) { logger.info(`Starting epoch ${epochIndex + 1} with ${numBlocks} blocks`); context.orchestrator.startNewEpoch(epochIndex + 1, epochIndex * numBlocks + 1, numBlocks); + const blockInEpoch = blocks.slice(epochIndex * numBlocks, (epochIndex + 1) * numBlocks); await Promise.all( - blocks.slice(epochIndex * numBlocks, (epochIndex + 1) * numBlocks).map(async ({ block, txs }) => { + blockInEpoch.map(async ({ block, txs }) => { await context.orchestrator.startNewBlock( block.header.globalVariables, [], @@ -128,7 +133,11 @@ describe('prover/orchestrator/multi-block', () => { logger.info('Finalising epoch'); const epoch = await context.orchestrator.finaliseEpoch(); - expect(epoch.publicInputs.endBlockNumber.toNumber()).toEqual(numBlocks + epochIndex * numBlocks); + const numProposedBlocks = countProposedBlocks(epoch.publicInputs.proposedBlockHeaderHashes); + expect(numProposedBlocks).toEqual(numBlocks); + expect(epoch.publicInputs.proposedBlockHeaderHashes.slice(0, numProposedBlocks)).toEqual( + blockInEpoch.map(b => b.block.header.toPropose().hash()), + ); expect(epoch.proof).toBeDefined(); } }, diff --git a/yarn-project/prover-node/src/prover-node-publisher.test.ts b/yarn-project/prover-node/src/prover-node-publisher.test.ts index 95f4394ef75c..f19f8844d61a 100644 --- a/yarn-project/prover-node/src/prover-node-publisher.test.ts +++ b/yarn-project/prover-node/src/prover-node-publisher.test.ts @@ -135,7 +135,7 @@ describe('prover-node-publisher', () => { // Return the requested block rollup.getBlock.mockImplementation((blockNumber: bigint) => Promise.resolve({ - archive: blocks[Number(blockNumber) - 1].endArchive.root.toString(), + archive: blocks[Number(blockNumber) - 1].endArchiveRoot.toString(), headerHash: '0x', // unused, slotNumber: 0n, // unused, }), @@ -144,8 +144,8 @@ describe('prover-node-publisher', () => { // We have built a rollup proof of the range fromBlock - toBlock // so we need to set our archives and hashes accordingly const ourPublicInputs = RootRollupPublicInputs.random(); - ourPublicInputs.previousArchive = blocks[fromBlock - 2]?.endArchive ?? Fr.ZERO; - ourPublicInputs.endArchive = blocks[toBlock - 1]?.endArchive ?? Fr.ZERO; + ourPublicInputs.previousArchiveRoot = blocks[fromBlock - 2]?.endArchiveRoot ?? Fr.ZERO; + ourPublicInputs.endArchiveRoot = blocks[toBlock - 1]?.endArchiveRoot ?? Fr.ZERO; // Return our public inputs const totalFields = ourPublicInputs.toFields(); diff --git a/yarn-project/prover-node/src/prover-node-publisher.ts b/yarn-project/prover-node/src/prover-node-publisher.ts index ba235cb8afdd..bfcf727dc1f4 100644 --- a/yarn-project/prover-node/src/prover-node-publisher.ts +++ b/yarn-project/prover-node/src/prover-node-publisher.ts @@ -162,17 +162,17 @@ export class ProverNodePublisher { // Check the archive for the immediate block before the epoch const blockLog = await this.rollupContract.getBlock(BigInt(fromBlock - 1)); - if (publicInputs.previousArchive.root.toString() !== blockLog.archive) { + if (publicInputs.previousArchiveRoot.toString() !== blockLog.archive) { throw new Error( - `Previous archive root mismatch: ${publicInputs.previousArchive.root.toString()} !== ${blockLog.archive}`, + `Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${blockLog.archive}`, ); } // Check the archive for the last block in the epoch const endBlockLog = await this.rollupContract.getBlock(BigInt(toBlock)); - if (publicInputs.endArchive.root.toString() !== endBlockLog.archive) { + if (publicInputs.endArchiveRoot.toString() !== endBlockLog.archive) { throw new Error( - `End archive root mismatch: ${publicInputs.endArchive.root.toString()} !== ${endBlockLog.archive}`, + `End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endBlockLog.archive}`, ); } @@ -249,10 +249,8 @@ export class ProverNodePublisher { BigInt(args.fromBlock), BigInt(args.toBlock), { - previousArchive: args.publicInputs.previousArchive.root.toString(), - endArchive: args.publicInputs.endArchive.root.toString(), - endTimestamp: args.publicInputs.endTimestamp.toBigInt(), - outHash: args.publicInputs.outHash.toString(), + previousArchive: args.publicInputs.previousArchiveRoot.toString(), + endArchive: args.publicInputs.endArchiveRoot.toString(), proverId: EthAddress.fromField(args.publicInputs.proverId).toString(), }, makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i => diff --git a/yarn-project/stdlib/src/rollup/root_rollup.ts b/yarn-project/stdlib/src/rollup/root_rollup.ts index 787762625937..138e727b4321 100644 --- a/yarn-project/stdlib/src/rollup/root_rollup.ts +++ b/yarn-project/stdlib/src/rollup/root_rollup.ts @@ -7,7 +7,6 @@ import { BufferReader, type Tuple, serializeToBuffer, serializeToFields } from ' import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import type { FieldsOf } from '@aztec/foundation/types'; -import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js'; import { FeeRecipient } from './block_root_or_block_merge_public_inputs.js'; import { PreviousRollupBlockData } from './previous_rollup_block_data.js'; @@ -100,13 +99,10 @@ export class RootRollupInputs { */ export class RootRollupPublicInputs { constructor( - /** Snapshot of archive tree before/after this rollup been processed */ - public previousArchive: AppendOnlyTreeSnapshot, - public endArchive: AppendOnlyTreeSnapshot, - // This is a u64 in nr, but GlobalVariables contains this as a u64 and is mapped to ts as a field, so I'm doing the same here - public endTimestamp: Fr, - public endBlockNumber: Fr, - public outHash: Fr, + /** Root of the archive tree before this rollup is processed */ + public previousArchiveRoot: Fr, + /** Root of the archive tree after this rollup is processed */ + public endArchiveRoot: Fr, public proposedBlockHeaderHashes: Tuple, public fees: Tuple, public chainId: Fr, @@ -119,11 +115,8 @@ export class RootRollupPublicInputs { static getFields(fields: FieldsOf) { return [ - fields.previousArchive, - fields.endArchive, - fields.endTimestamp, - fields.endBlockNumber, - fields.outHash, + fields.previousArchiveRoot, + fields.endArchiveRoot, fields.proposedBlockHeaderHashes, fields.fees, fields.chainId, @@ -155,9 +148,6 @@ export class RootRollupPublicInputs { public static fromBuffer(buffer: Buffer | BufferReader): RootRollupPublicInputs { const reader = BufferReader.asReader(buffer); return new RootRollupPublicInputs( - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readArray(AZTEC_MAX_EPOCH_DURATION, Fr), @@ -192,9 +182,6 @@ export class RootRollupPublicInputs { /** Creates a random instance. */ static random() { return new RootRollupPublicInputs( - AppendOnlyTreeSnapshot.random(), - AppendOnlyTreeSnapshot.random(), - Fr.random(), Fr.random(), Fr.random(), makeTuple(AZTEC_MAX_EPOCH_DURATION, Fr.random), diff --git a/yarn-project/stdlib/src/tests/factories.ts b/yarn-project/stdlib/src/tests/factories.ts index 3bbdd6a7585f..a72a566092d6 100644 --- a/yarn-project/stdlib/src/tests/factories.ts +++ b/yarn-project/stdlib/src/tests/factories.ts @@ -880,13 +880,10 @@ export function makeRootParityInputs(seed = 0): RootParityInputs { */ export function makeRootRollupPublicInputs(seed = 0): RootRollupPublicInputs { return new RootRollupPublicInputs( - makeAppendOnlyTreeSnapshot(seed + 0x100), - makeAppendOnlyTreeSnapshot(seed + 0x200), - fr(seed + 0x300), - fr(seed + 0x400), - fr(seed + 0x500), - makeTuple(AZTEC_MAX_EPOCH_DURATION, () => fr(seed), 0x650), - makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeFeeRecipient(seed), 0x600), + fr(seed + 0x100), + fr(seed + 0x200), + makeTuple(AZTEC_MAX_EPOCH_DURATION, () => fr(seed), 0x300), + makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeFeeRecipient(seed), 0x500), fr(seed + 0x700), fr(seed + 0x701), fr(seed + 0x702),