diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr index 1222d8c19bab..fcb8f062c11f 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr @@ -6,6 +6,8 @@ use types::{ utils::reader::Reader, }; +// TODO(MW): delete + // NB: This only exists because a nested array of [[Field; 2]; N] did not build with ci2.5, but was fine otherwise // For blobs, we use the compressed 48 byte BLS12 commitment to compute the challenge. We never need to operate on it, // so it's encoded as 2 fields. The first is the first 31 bytes, and the second is the next 17 bytes. diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml index 12e1bcfbd51e..d07ba1cefe98 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml @@ -5,6 +5,7 @@ authors = [""] compiler_version = ">=0.18.0" [dependencies] +bigint = { tag = "v0.7.3", git = "https://github.com/noir-lang/noir-bignum" } types = { path = "../types" } parity_lib = { path = "../parity-lib" } blob = { path = "../blob" } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr index 28ef80788036..0a63d32e7b02 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr @@ -8,7 +8,7 @@ use dep::types::{ traits::{Deserialize, Empty, Serialize, ToField}, utils::reader::Reader, }; -use blob::blob_public_inputs::BlockBlobPublicInputs; +use blob::blob_batching_public_inputs::BlockBlobPublicInputs; pub struct FeeRecipient { pub recipient: EthAddress, @@ -53,7 +53,7 @@ pub struct BlockRootOrBlockMergePublicInputs { pub vk_tree_root: Field, // Root of allowed vk tree pub protocol_contract_tree_root: Field, // Root of protocol contract tree pub prover_id: Field, // TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1 - pub blob_public_inputs: [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], // z, y, and C s.t. p(z) = y and C commits to p, for blob verification + pub blob_public_inputs: BlockBlobPublicInputs, // Blob accumulators at the start and end of this block range } impl BlockRootOrBlockMergePublicInputs { @@ -75,7 +75,7 @@ impl Empty for BlockRootOrBlockMergePublicInputs { vk_tree_root: 0, protocol_contract_tree_root: 0, prover_id: 0, - blob_public_inputs: [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], + blob_public_inputs: BlockBlobPublicInputs::empty(), } } } @@ -113,9 +113,7 @@ impl Serialize for BlockRootOrBl fields.push(self.vk_tree_root); fields.push(self.protocol_contract_tree_root); fields.push(self.prover_id as Field); - for i in 0..AZTEC_MAX_EPOCH_DURATION { - fields.extend_from_array(self.blob_public_inputs[i].serialize()); - } + fields.extend_from_array(self.blob_public_inputs.serialize()); assert_eq(fields.len(), BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH); fields.storage() @@ -141,10 +139,7 @@ impl Deserialize for BlockRootOr vk_tree_root: reader.read(), protocol_contract_tree_root: reader.read(), prover_id: reader.read(), - blob_public_inputs: reader.read_struct_array( - BlockBlobPublicInputs::deserialize, - [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], - ), + blob_public_inputs: reader.read_struct(BlockBlobPublicInputs::deserialize), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_rollup_data.nr index c67cdc19c60d..594c40c65081 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_rollup_data.nr @@ -1,4 +1,6 @@ -use blob::blob_public_inputs::BlobCommitment; +use blob::blob_batching_public_inputs::{ + BlobAccumulatorPublicInputs, BLSPoint, FinalBlobBatchingChallenges, +}; use parity_lib::root::root_rollup_parity_input::RootRollupParityInput; use types::{ block_header::BlockHeader, @@ -23,17 +25,29 @@ pub struct BlockRootRollupData { // Its hash is checked against the previous archive. pub previous_block_header: BlockHeader, + // <-- NOTE: start_blob_accumulator and final_blob_challenges exist here and not BlockRootRollupBlobData + // so we can inject easily into EmptyBlockRootRollupInputs: + + // The current blob accumulation state across the epoch. + // Injected here and checked vs the previous end state in each block merge and root rollup circuit: + pub start_blob_accumulator: BlobAccumulatorPublicInputs, + // Finalized challenges z and gamma for performing blob batching. Shared value across the epoch + // Precompjuted, injected here, and confirmed in the root rollup circuit: + pub final_blob_challenges: FinalBlobBatchingChallenges, + + // --> + // TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1 pub prover_id: Field, } pub struct BlockRootRollupBlobData { // Fields for blob verification made of all tx effects in this block - // (will likely change to be accumulated and sent up to the final root) pub blobs_fields: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], - // see blob/src/blob.nr -> evaluate_blob() - these are used for creating the challenge z - pub blob_commitments: [BlobCommitment; BLOBS_PER_BLOCK], + // see blob/src/blob.nr -> evaluate_blob() - these are used for creating each blob's challenge z_i + pub blob_commitments: [BLSPoint; BLOBS_PER_BLOCK], // Flat sha256 hash of the EVM blob hashes, can be injected here as the contract checks its validity vs the blob_public_inputs // NB: to fit it into a field, we truncate to 31 bytes + // TODO(MW): Replace with v? pub blobs_hash: Field, } 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 a9e1489bc68d..c2dc585999a1 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 @@ -8,6 +8,7 @@ use dep::types::{ }, traits::Empty, }; +use blob::blob_batching_public_inputs::BlockBlobPublicInputs; global ALLOWED_PREVIOUS_CIRCUITS: [u32; 4] = [ BLOCK_ROOT_ROLLUP_INDEX, @@ -54,11 +55,11 @@ impl BlockMergeRollupInputs { let fees = components::accumulate_blocks_fees(left, right); - // TODO: We need to eventually accumulate blob info to a single BlobPublicInputs instance which will verify multiple blobs in one call - // For now, we do them individually - // How we accumulate is being worked on by @Mike - // let blob_public_inputs = left.blob_public_inputs.accumulate(right.blob_public_inputs); - let blob_public_inputs = components::accumulate_blob_public_inputs(left, right); + let blob_public_inputs = BlockBlobPublicInputs { + start_blob_accumulator: left.blob_public_inputs.start_blob_accumulator, + end_blob_accumulator: right.blob_public_inputs.end_blob_accumulator, + final_blob_challenges: left.blob_public_inputs.final_blob_challenges, + }; // TODO(MW): Batching here will consist of checks: // - left.end_blob_accumulator == right.start_blob_accumulator @@ -107,6 +108,14 @@ mod tests { let _output = inputs.block_merge_rollup_circuit(); } + #[test(should_fail_with = "input blocks have different epoch blob challenges")] + fn blob_different_challenges_fails() { + let mut inputs = default_block_merge_rollup_inputs(); + inputs.previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.final_blob_challenges.z += + 1; + let _output = inputs.block_merge_rollup_circuit(); + } + #[test(should_fail_with = "input blocks have different archive tree snapshots")] fn previous_rollups_dont_follow_archive() { let mut inputs = default_block_merge_rollup_inputs(); @@ -126,6 +135,14 @@ mod tests { let _output = inputs.block_merge_rollup_circuit(); } + #[test(should_fail_with = "input block blob accumulators do not follow on from each other")] + fn previous_rollups_dont_follow_blob_accumulator() { + let mut inputs = default_block_merge_rollup_inputs(); + inputs.previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.z_acc += + 1; + let _output = inputs.block_merge_rollup_circuit(); + } + #[test] fn block_fees_are_accumulated() { let mut inputs = default_block_merge_rollup_inputs(); @@ -156,16 +173,18 @@ mod tests { let outputs = inputs.block_merge_rollup_circuit(); assert_eq( - outputs.blob_public_inputs[0], + outputs.blob_public_inputs.start_blob_accumulator, inputs.previous_rollup_data[0] .block_root_or_block_merge_public_inputs - .blob_public_inputs[0], + .blob_public_inputs + .start_blob_accumulator, ); assert_eq( - outputs.blob_public_inputs[1], + outputs.blob_public_inputs.end_blob_accumulator, inputs.previous_rollup_data[1] .block_root_or_block_merge_public_inputs - .blob_public_inputs[0], + .blob_public_inputs + .end_blob_accumulator, ); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr index 04459094cf1b..c02a1900f3e9 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr @@ -49,9 +49,13 @@ pub(crate) mod tests { block_root::block_root_rollup_inputs::BlockRootRollupInputs, tests::rollup_fixture_builder::RollupFixtureBuilder, }; - use poseidon::poseidon2::Poseidon2; + use bigint::{BigNum, BLS12_381_Fr as F}; + use blob::blob_batching_public_inputs::BatchingBlobCommitment; use types::{ - hash::accumulate_sha256, tests::utils::assert_array_eq, utils::arrays::array_concat, + constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, + hash::{accumulate_sha256, poseidon2_hash}, + tests::utils::assert_array_eq, + utils::arrays::array_concat, }; pub struct TestBuilder { @@ -61,7 +65,7 @@ pub(crate) mod tests { impl TestBuilder { pub fn new() -> Self { let inputs = RollupFixtureBuilder::new_for_block_root(); - inputs.mock_evaluate_blobs(); + inputs.mock_evaluate_blobs_and_batch(); TestBuilder { inputs } } @@ -133,18 +137,35 @@ pub(crate) mod tests { 0x0000000000000000000000000000000000000000000000000000000004000001, 0x0000000000000000000000000000000000000000000000000000000000000045, ]; - let expected_blob_commitment = [ + + let expected_blob_commitment_fields_fixture = [ 0x008c32fe581c8fdba12c0d7597911dead2d937d68525bae655508412bb53bb98, 0x0000000000000000000000000000006aaa0680f21270e7d8de4e19da5164f95c, ]; - let expected_blobs_hash = - 0x00a965619c8668b834755678b32d023b9c5e8588ce449f44f7fa9335455b5cc5; - let expected_challenge_z = + let expected_challenge_z_fixture = 0x1f92b871671f27a378d23f1cef10fbd8f0d90dd7172da9e3c3fc1aa745a072c3; + // Blob commitment with value: + // x: 0x0c32fe581c8fdba12c0d7597911dead2d937d68525bae655508412bb53bb986aaa0680f21270e7d8de4e19da5164f95c, + // y: 0x07896936b96e9af0ecd6ef882c14dcc6e8d075ea61d11ae9df4bfab87396547b5e01b8a35d9a720733acdd92421f24e9, + let mut injected_blob_commitment = BatchingBlobCommitment::from_limbs( + [ + 0x0680f21270e7d8de4e19da5164f95c, + 0xd68525bae655508412bb53bb986aaa, + 0x581c8fdba12c0d7597911dead2d937, + 0x0c32fe, + ], + [ + 0x01b8a35d9a720733acdd92421f24e9, + 0x75ea61d11ae9df4bfab87396547b5e, + 0x36b96e9af0ecd6ef882c14dcc6e8d0, + 0x078969, + ], + ); + let injected_blob_commitment_fields = injected_blob_commitment.to_compressed_fields(); + let mut builder = TestBuilder::new_with_blobs_fields(blob_fields_0, blob_fields_1); - builder.inputs.blob_commitments[0].inner = expected_blob_commitment; - builder.inputs.blobs_hash = expected_blobs_hash; + builder.inputs.blob_commitments[0] = injected_blob_commitment.point; let output = builder.execute(); @@ -161,16 +182,152 @@ pub(crate) mod tests { assert(end_sponge_blob.eq(expected_sponge)); let hashed_tx_effects = expected_sponge.squeeze(); - let computed_challenge_z = Poseidon2::hash( - [hashed_tx_effects, expected_blob_commitment[0], expected_blob_commitment[1]], - 3, + let expected_challenge_z = poseidon2_hash([ + hashed_tx_effects, + injected_blob_commitment_fields[0], + injected_blob_commitment_fields[1], + ]); + let expected_gamma_acc = poseidon2_hash(output + .blob_public_inputs + .end_blob_accumulator + .y_acc + .get_limbs() + .map(|l| l as Field)); + + // We have a single blob, so the accumulated outputs are just those after a single evaluation: + assert_eq(output.blob_public_inputs.end_blob_accumulator.z_acc, expected_challenge_z); + assert_eq( + output.blob_public_inputs.end_blob_accumulator.z_acc, + expected_challenge_z_fixture, ); - assert_eq(computed_challenge_z, expected_challenge_z); - assert_eq(output.blob_public_inputs[0].inner[0].z, expected_challenge_z); assert_eq( - output.blob_public_inputs[0].inner[0].kzg_commitment.inner, - expected_blob_commitment, + output.blob_public_inputs.end_blob_accumulator.c_acc, + injected_blob_commitment.point, ); + assert_eq(injected_blob_commitment_fields, expected_blob_commitment_fields_fixture); + assert_eq(output.blob_public_inputs.end_blob_accumulator.gamma_acc, expected_gamma_acc); + } + + // All hardcoded values in this test are taken from yarn-project/foundation/src/blob/blob_batching.test.ts -> 'should construct and verify a batch of 3 full blobs' + // These values are also used in blob_batching.nr -> test_full_blobs_batched(), but the below ensures inputs are propagated properly throughout block_root + #[test] + unconstrained fn correct_blobs_with_non_empty_fields() { + // Fill three blobs completely with different values (to avoid a constant polynomial) + let mut blob: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK] = + [0; FIELDS_PER_BLOB * BLOBS_PER_BLOCK]; + for j in 0..BLOBS_PER_BLOCK { + for i in 0..FIELDS_PER_BLOB { + blob[j * FIELDS_PER_BLOB + i] = ((j + 3) * (i + 1)) as Field; + } + } + // Init. injected values: + // - Commitments are injected and checked for correctness on L1 via acc.v + let kzg_commitments_in = [ + BatchingBlobCommitment::from_limbs( + [ + 0x2627fc88755984d7f002e5ef0e6b3e, + 0x0ea98f6a26672e17f919eb020b00ee, + 0xea6e5173f2ef1bedbb07bfa9ac6ed8, + 0x01c6e6, + ], + [ + 0xaa96f04ba1d419683f218cc4f15a3f, + 0x8887c5e719583b765309e4b3d18752, + 0x9ff512de37b8582f7167fdfbb29539, + 0x18f531, + ], + ) + .point, + BatchingBlobCommitment::from_limbs( + [ + 0x71556bb7217816fbb3f822fc873740, + 0x9c57d93d7fd33a388e13e95cfdba95, + 0x4f0ddbdc9d6a3653cd825ebd9f5730, + 0x12324e, + ], + [ + 0xabf9f60fc773ef1802a706d6b170a4, + 0x788f9000166d54151ac05df44e63be, + 0x0a8b45ead129885bb12837fb59033b, + 0x12aadd, + ], + ) + .point, + BatchingBlobCommitment::from_limbs( + [ + 0x69afb94a09e713e7fb94e26f33c3ed, + 0x8161293f65480c3b7bad57aaef1984, + 0xc34d68dc32d1ecd46f46ec4c969bb1, + 0x0d97ef, + ], + [ + 0x9837a79d9fa4d0370198419b273360, + 0x9e7340f07732e2cb3d51db22b1dcb3, + 0x8285e8cad42f634bb51ad7d2c68a12, + 0x07db3c, + ], + ) + .point, + ]; + + let mut builder = TestBuilder::new_with_blobs_fields(blob, []); + + let start_sponge_blob = builder.inputs.previous_rollup_data[0] + .base_or_merge_rollup_public_inputs + .start_sponge_blob; + let mut expected_sponge = start_sponge_blob; + expected_sponge.absorb(blob, FIELDS_PER_BLOB * BLOBS_PER_BLOCK); + builder.inputs.blob_commitments = kzg_commitments_in; + // - The final z value is injected and checked for correctness in root (see below final_acc) + builder.inputs.final_blob_challenges.z = + 0x02d6a54e591ada73e5eea35188a02ac87779f4293ea3e7d675fa50ae7ff332ce; + // - The final gamma value is injected and checked for correctness in root (see below final_acc) + builder.inputs.final_blob_challenges.gamma = F::from_limbs([ + 0x281287a8d44071d216177e06a02327, + 0x16571aa3dcfef75c2447c705c6c68a, + 0x16f2, + ]); + + let output = builder.execute(); + let final_acc = output.blob_public_inputs.end_blob_accumulator; + + assert_eq(final_acc.z_acc, builder.inputs.final_blob_challenges.z); + + // y is a BLS Fr field with value 0x0cd2fd9a46ba70fd7f212d08ec7283024b0b1ff9446b1f78a482fb7443e49b57 + let expected_y_limbs = + [0x0b1ff9446b1f78a482fb7443e49b57, 0xfd9a46ba70fd7f212d08ec7283024b, 0x0cd2]; + + // C is a BLS point with value: + // x: 0x0f2f5f62cc6c3ab4c1ac1abcb9da9677e12796a76064f68c0d4f659f25a046a6d42616100269935afcb1b98c85d5e93e, + // y: 0x0af1e4abfa449daf65201c2b24507b1058d8ea9bf82ff948a1d01912615c4a8e507160da282e6c41bab917c868923254, + let expected_c = BatchingBlobCommitment::from_limbs( + [ + 0x2616100269935afcb1b98c85d5e93e, + 0x96a76064f68c0d4f659f25a046a6d4, + 0x62cc6c3ab4c1ac1abcb9da9677e127, + 0x0f2f5f, + ], + [ + 0x7160da282e6c41bab917c868923254, + 0xea9bf82ff948a1d01912615c4a8e50, + 0xabfa449daf65201c2b24507b1058d8, + 0x0af1e4, + ], + ) + .point; + + assert(builder.inputs.previous_rollup_data[1] + .base_or_merge_rollup_public_inputs + .end_sponge_blob + .eq(expected_sponge)); + + // blob_commitments_hash is a BN Fr field with value 0x00d2f7bffbc5a9008207a188e348e753087f54557a686efd7f74c90cac52a9a1 + let expected_blob_commitments_hash = + 0xd2f7bffbc5a9008207a188e348e753087f54557a686efd7f74c90cac52a9a1; + + assert_eq(final_acc.y_acc.get_limbs(), expected_y_limbs); + assert_eq(final_acc.c_acc, expected_c); + assert_eq(final_acc.blob_commitments_hash_acc, expected_blob_commitments_hash); } #[test(should_fail_with = "block's first blob sponge was not empty")] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/components/block_root_rollup_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/components/block_root_rollup_output_composer.nr index 31933c45eb1e..41e861b13990 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/components/block_root_rollup_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/components/block_root_rollup_output_composer.nr @@ -6,7 +6,12 @@ use crate::{ }, merge::utils::merge_rollups::merge_rollups, }; -use blob::{blob::evaluate_blobs, blob_public_inputs::{BlobPublicInputs, BlockBlobPublicInputs}}; +use blob::{ + blob_batching::evaluate_blobs_and_batch, + blob_batching_public_inputs::{ + BlobAccumulationInputs, BlobAccumulatorPublicInputs, BlockBlobPublicInputs, + }, +}; use types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, constant_rollup_data::ConstantRollupData, @@ -18,7 +23,7 @@ use types::{ partial_state_reference::PartialStateReference, proposed_block_header::ProposedBlockHeader, state_reference::StateReference, - traits::{Empty, Hash}, + traits::{Empty, Hash, is_empty}, }; pub struct BlockRootRollupOutputComposer { @@ -59,14 +64,15 @@ impl BlockRootRollupOutputComposer { let new_archive = self.update_archive(constants.last_archive, new_block_hash); let proposed_block_header_hash = self.create_proposed_block_header(new_block_header).hash(); - let block_blob_public_inputs = self.get_block_blob_public_inputs(blob_data); + let end_blob_accumulator = self.get_blob_accumulator_public_inputs(blob_data); self.finish_with_new_values( constants, new_archive, proposed_block_header_hash, self.merged_rollup.out_hash, - block_blob_public_inputs, + self.data.start_blob_accumulator, + end_blob_accumulator, self.merged_rollup.accumulated_fees, ) } @@ -75,7 +81,7 @@ impl BlockRootRollupOutputComposer { self, constants: ConstantRollupData, empty_effect_blobs_hash: Field, - empty_effect_blob_public_input: BlobPublicInputs, + empty_effect_blob_accumulation_input: BlobAccumulationInputs, is_padding: bool, ) -> BlockRootOrBlockMergePublicInputs { let (new_archive, proposed_block_header_hash) = if is_padding { @@ -93,9 +99,20 @@ impl BlockRootRollupOutputComposer { ) }; - let mut block_blob_public_inputs = BlockBlobPublicInputs::empty(); - if !is_padding { - block_blob_public_inputs.inner[0] = empty_effect_blob_public_input; + let end_blob_accumulator = if is_padding { + self.data.start_blob_accumulator + } else { + if is_empty(self.data.start_blob_accumulator) { + BlobAccumulatorPublicInputs::init( + empty_effect_blob_accumulation_input, + self.data.final_blob_challenges.gamma, + ) + } else { + self.data.start_blob_accumulator.accumulate( + empty_effect_blob_accumulation_input, + self.data.final_blob_challenges.gamma, + ) + } }; self.finish_with_new_values( @@ -103,7 +120,8 @@ impl BlockRootRollupOutputComposer { new_archive, proposed_block_header_hash, 0 /* out_hash */, - block_blob_public_inputs, + self.data.start_blob_accumulator, + end_blob_accumulator, 0, /* accumulated_fees */ ) } @@ -114,7 +132,8 @@ impl BlockRootRollupOutputComposer { new_archive: AppendOnlyTreeSnapshot, proposed_block_header_hash: Field, out_hash: Field, - block_blob_public_inputs: BlockBlobPublicInputs, + start_blob_accumulator: BlobAccumulatorPublicInputs, + end_blob_accumulator: BlobAccumulatorPublicInputs, accumulated_fees: Field, ) -> BlockRootOrBlockMergePublicInputs { let mut proposed_block_header_hashes = [0; AZTEC_MAX_EPOCH_DURATION]; @@ -126,8 +145,11 @@ impl BlockRootRollupOutputComposer { value: accumulated_fees, }; - let mut blob_public_inputs = [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; - blob_public_inputs[0] = block_blob_public_inputs; + let blob_public_inputs = BlockBlobPublicInputs { + start_blob_accumulator, + end_blob_accumulator, + final_blob_challenges: self.data.final_blob_challenges, + }; BlockRootOrBlockMergePublicInputs { previous_archive: constants.last_archive, // archive before this block was added @@ -209,22 +231,33 @@ impl BlockRootRollupOutputComposer { ) } - fn get_block_blob_public_inputs(self, data: BlockRootRollupBlobData) -> BlockBlobPublicInputs { - if !dep::std::runtime::is_unconstrained() { - evaluate_blobs( - data.blobs_fields, - data.blob_commitments, - self.merged_rollup.end_sponge_blob, - ) - } else { - // Safety: TODO(#10323): this was added to save simulation time, if/when simulation times of unconstrained are improved, remove this. - unsafe { - blob::mock_blob_oracle::evaluate_blobs( - data.blobs_fields, - data.blob_commitments, - self.merged_rollup.end_sponge_blob, - ) - } - } + fn get_blob_accumulator_public_inputs( + self, + data: BlockRootRollupBlobData, + ) -> BlobAccumulatorPublicInputs { + evaluate_blobs_and_batch( + data.blobs_fields, + data.blob_commitments, + self.merged_rollup.end_sponge_blob, + self.data.final_blob_challenges, + self.data.start_blob_accumulator, + ) + // TODO(MW): Remove below once simulation of above is tested + // if !dep::std::runtime::is_unconstrained() { + // evaluate_blobs( + // data.blobs_fields, + // data.blob_commitments, + // self.merged_rollup.end_sponge_blob, + // ) + // } else { + // // Safety: TODO(#10323): this was added to save simulation time, if/when simulation times of unconstrained are improved, remove this. + // unsafe { + // blob::mock_blob_oracle::evaluate_blobs( + // data.blobs_fields, + // data.blob_commitments, + // self.merged_rollup.end_sponge_blob, + // ) + // } + // } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr index 9d326c9a9dd7..ad674158650f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr @@ -8,13 +8,13 @@ use crate::{ block_root_rollup_output_composer::BlockRootRollupOutputComposer, }, }; -use blob::blob_public_inputs::BlobPublicInputs; +use blob::blob_batching_public_inputs::{BatchingBlobCommitment, BlobAccumulationInputs}; use types::{abis::constant_rollup_data::ConstantRollupData, traits::Empty}; pub global EMPTY_EFFECT_BLOBS_HASH: Field = 0x001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d9; -pub global EMPTY_EFFECT_BLOB_COMMITMENT: [Field; 2] = - [0x00c0000000000000000000000000000000000000000000000000000000000000, 0]; +pub global EMPTY_EFFECT_BLOB_COMMITMENT: BatchingBlobCommitment = + BatchingBlobCommitment::empty_blob(); pub global EMPTY_EFFECT_BLOB_CHALLENGE_Z: Field = 0x0ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb; @@ -35,15 +35,15 @@ impl EmptyBlockRootRollupInputs { ); validator.validate_without_previous_rollups(self.is_padding, self.constants.last_archive); - let mut blob_public_input = BlobPublicInputs::empty(); - blob_public_input.kzg_commitment.inner = EMPTY_EFFECT_BLOB_COMMITMENT; - blob_public_input.z = EMPTY_EFFECT_BLOB_CHALLENGE_Z; + let mut blob_accumulation_input = BlobAccumulationInputs::empty(); + blob_accumulation_input.z_i = EMPTY_EFFECT_BLOB_CHALLENGE_Z; + blob_accumulation_input.c_i = EMPTY_EFFECT_BLOB_COMMITMENT; let composer = BlockRootRollupOutputComposer::new_from_empty_rollup(self.data); composer.finish_empty( self.constants, EMPTY_EFFECT_BLOBS_HASH, - blob_public_input, + blob_accumulation_input, self.is_padding, ) } @@ -60,8 +60,11 @@ mod tests { }, tests::rollup_fixture_builder::RollupFixtureBuilder, }; - use poseidon::poseidon2::Poseidon2; - use types::{abis::sponge_blob::SpongeBlob, address::EthAddress, tests::utils::assert_array_eq}; + use bigint::BigNum; + use types::{ + abis::sponge_blob::SpongeBlob, address::EthAddress, hash::poseidon2_hash, + tests::utils::assert_array_eq, + }; pub struct TestBuilder { pub inputs: RollupFixtureBuilder, @@ -101,32 +104,36 @@ mod tests { // The below values are generated from block_building_helper.test.ts. let expected_empty_effect_blobs_hash = 0x001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d9; - let expected_empty_effect_blob_commitment = + let expected_empty_effect_blob_commitment_fields = [0x00c0000000000000000000000000000000000000000000000000000000000000, 0]; let expected_empty_effect_challenge_z = 0x0ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb; assert_eq(expected_empty_effect_blobs_hash, EMPTY_EFFECT_BLOBS_HASH); - assert_eq(expected_empty_effect_blob_commitment, EMPTY_EFFECT_BLOB_COMMITMENT); + assert_eq( + expected_empty_effect_blob_commitment_fields, + EMPTY_EFFECT_BLOB_COMMITMENT.to_compressed_fields(), + ); assert_eq(expected_empty_effect_challenge_z, EMPTY_EFFECT_BLOB_CHALLENGE_Z); let mut expected_sponge = SpongeBlob::new(0); let hashed_tx_effects = expected_sponge.squeeze(); - let computed_z = Poseidon2::hash( - [ - hashed_tx_effects, - expected_empty_effect_blob_commitment[0], - expected_empty_effect_blob_commitment[1], - ], - 3, - ); + let computed_z = poseidon2_hash([ + hashed_tx_effects, + expected_empty_effect_blob_commitment_fields[0], + expected_empty_effect_blob_commitment_fields[1], + ]); - assert_eq(computed_z, expected_empty_effect_challenge_z); - assert_eq(output.blob_public_inputs[0].inner[0].z, expected_empty_effect_challenge_z); + assert_eq(computed_z, EMPTY_EFFECT_BLOB_CHALLENGE_Z); assert_eq( - output.blob_public_inputs[0].inner[0].kzg_commitment.inner, - expected_empty_effect_blob_commitment, + output.blob_public_inputs.end_blob_accumulator.z_acc, + EMPTY_EFFECT_BLOB_CHALLENGE_Z, ); + assert_eq( + output.blob_public_inputs.end_blob_accumulator.c_acc, + EMPTY_EFFECT_BLOB_COMMITMENT.point, + ); + assert_eq(output.blob_public_inputs.end_blob_accumulator.y_acc.get_limbs(), [0, 0, 0]); } #[test] @@ -140,8 +147,11 @@ mod tests { assert_eq(output.previous_archive, output.new_archive); assert_eq(output.start_global_variables, output.end_global_variables); assert_eq(output.out_hash, 0); + assert_eq( + output.blob_public_inputs.start_blob_accumulator, + output.blob_public_inputs.end_blob_accumulator, + ); assert_array_eq(output.fees, []); - assert_array_eq(output.blob_public_inputs, []); } #[test(should_fail_with = "hash of the previous block header is not the last leaf in the archive tree")] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/single_tx_block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/single_tx_block_root_rollup_inputs.nr index 078161ca9118..96553610e777 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/single_tx_block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/single_tx_block_root_rollup_inputs.nr @@ -71,7 +71,7 @@ mod tests { #[test] unconstrained fn single_tx_block_root_rollup_output_propagated_from_base() { let builder = TestBuilder::new(); - builder.inputs.mock_evaluate_blobs(); + builder.inputs.mock_evaluate_blobs_and_batch(); let output = builder.execute(); 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 3ba26691c429..0af30f3dabd9 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 @@ -19,10 +19,9 @@ use dep::types::{ }, hash::compute_contract_class_log_hash, merkle_tree::VariableMerkleTree, - traits::{Empty, ToField}, + traits::ToField, utils::arrays::{array_length, array_length_until, array_merge, array_padded_with}, }; -use blob::blob_public_inputs::BlockBlobPublicInputs; pub fn assert_prev_block_rollups_follow_on_from_each_other( left: BlockRootOrBlockMergePublicInputs, @@ -45,6 +44,18 @@ pub fn assert_prev_block_rollups_follow_on_from_each_other( left.end_global_variables.version == right.start_global_variables.version, "input blocks have different chain version", ); + assert( + left.blob_public_inputs.end_blob_accumulator.eq( + right.blob_public_inputs.start_blob_accumulator, + ), + "input block blob accumulators do not follow on from each other", + ); + assert( + left.blob_public_inputs.final_blob_challenges.eq( + right.blob_public_inputs.final_blob_challenges, + ), + "input blocks have different epoch blob challenges", + ); if right.is_padding() { assert( @@ -87,28 +98,6 @@ pub fn accumulate_blocks_fees( array_merge(left.fees, right.fees) } -// TODO: This fn will be obselete once we have integrated accumulation of blob PIs -// The goal is to acc. the commitments and openings s.t. one set verifies the opening of many blobs -// How we accumulate is being worked on by @Mike -pub fn accumulate_blob_public_inputs( - left: BlockRootOrBlockMergePublicInputs, - right: BlockRootOrBlockMergePublicInputs, -) -> [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION] { - let left_len = array_length(left.blob_public_inputs); - // 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]; - for i in 0..result.len() { - add_from_left &= i != left_len; - if (add_from_left) { - result[i] = left.blob_public_inputs[i]; - } else { - result[i] = right.blob_public_inputs[i - left_len]; - } - } - result -} - 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 72d664b7c1b2..92a21000a8ba 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 @@ -43,9 +43,35 @@ mod tests { assert_eq(outputs.prover_id, left.prover_id); assert_eq(outputs.prover_id, right.prover_id); - assert_array_eq( + assert_eq( outputs.blob_public_inputs, - [left.blob_public_inputs[0], right.blob_public_inputs[0]], + right.blob_public_inputs.end_blob_accumulator.finalize_and_validate( + left.blob_public_inputs.final_blob_challenges, + ), ); } + + #[test(should_fail_with = "Epoch did not start with empty blob state.")] + unconstrained fn non_empty_start_blob_fails() { + let mut inputs = default_root_rollup_inputs(); + inputs.previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.start_blob_accumulator.z_acc += + 1; + let _output = inputs.root_rollup_circuit(); + } + + #[test(should_fail_with = "Final blob challenge z mismatch.")] + unconstrained fn blob_different_challenge_z_fails() { + let mut inputs = default_root_rollup_inputs(); + inputs.previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.z_acc += + 1; + let _output = inputs.root_rollup_circuit(); + } + + #[test(should_fail_with = "Final blob challenge gamma mismatch.")] + unconstrained fn blob_different_challenge_gamma_fails() { + let mut inputs = default_root_rollup_inputs(); + inputs.previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.gamma_acc += + 1; + let _output = inputs.root_rollup_circuit(); + } } 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 e0f034053008..f957ca3f37dd 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 @@ -7,7 +7,7 @@ use types::{ 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, + traits::{Empty, is_empty}, }; global ALLOWED_PREVIOUS_CIRCUITS: [u32; 4] = [ @@ -66,11 +66,10 @@ impl RootRollupInputs { let fees = components::accumulate_blocks_fees(left, right); - // TODO: We need to eventually accumulate blob info to a single BlobPublicInputs instance which will verify multiple blobs in one call - // For now, we do them individually - // How we accumulate is being worked on by @Mike - // let blob_public_inputs = left.blob_public_inputs.accumulate(right.blob_public_inputs); - let blob_public_inputs = components::accumulate_blob_public_inputs(left, right); + assert( + is_empty(left.blob_public_inputs.start_blob_accumulator), + "Epoch did not start with empty blob state.", + ); // TODO(MW): Batching here will consist of checks: // - left.end_blob_accumulator == right.start_blob_accumulator @@ -94,7 +93,9 @@ impl RootRollupInputs { vk_tree_root: left.vk_tree_root, protocol_contract_tree_root: left.protocol_contract_tree_root, prover_id: self.prover_id, - blob_public_inputs, + blob_public_inputs: right.blob_public_inputs.end_blob_accumulator.finalize_and_validate( + left.blob_public_inputs.final_blob_challenges, + ), } } } 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 22c487ea9aab..0d9338b4279d 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,7 +1,6 @@ use crate::abis::block_root_or_block_merge_public_inputs::FeeRecipient; use dep::types::constants::AZTEC_MAX_EPOCH_DURATION; -use blob::blob_public_inputs::BlockBlobPublicInputs; - +use blob::blob_batching_public_inputs::FinalBlobAccumulatorPublicInputs; pub struct RootRollupPublicInputs { // Snapshot of archive tree before/after this rollup has been processed pub previous_archive_root: Field, @@ -13,5 +12,5 @@ pub struct RootRollupPublicInputs { pub vk_tree_root: Field, pub protocol_contract_tree_root: Field, pub prover_id: Field, - pub blob_public_inputs: [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], + pub blob_public_inputs: FinalBlobAccumulatorPublicInputs, } 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 948fcad16586..1545c476d938 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 @@ -3,6 +3,7 @@ use dep::types::{ abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::BLOCK_ROOT_ROLLUP_INDEX, merkle_tree::merkle_tree::MerkleTree, proof::vk_data::VkData, tests::fixtures, traits::Empty, }; +use bigint::{BigNum, BLS12_381_Fr as F}; pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { let mut previous_rollup_data = [PreviousRollupBlockData::empty(); 2]; @@ -53,10 +54,33 @@ pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { 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; - previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs[0].inner[0].z = + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.z_acc = 1; - previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs[0].inner[0].z = + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.blob_commitments_hash_acc = 2; + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.gamma_acc = + 3; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.start_blob_accumulator = previous_rollup_data[0] + .block_root_or_block_merge_public_inputs + .blob_public_inputs + .end_blob_accumulator; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.z_acc = + 4; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.blob_commitments_hash_acc = + 5; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.end_blob_accumulator.gamma_acc = + 6; + + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.final_blob_challenges.z = + 4; + // = poseidon2([6, 4]) = 0x25f106373d285972efcdfcbc99096a989156495514c4e1bc6cfac2b288ade5e7: + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs.final_blob_challenges.gamma = F::from_limbs( + [448024886556591125833969477526349287, 32274159084860741962424622034622609, 9713], + ); + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs.final_blob_challenges = previous_rollup_data[0] + .block_root_or_block_merge_public_inputs + .blob_public_inputs + .final_blob_challenges; previous_rollup_data } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/rollup_fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/rollup_fixture_builder.nr index 7c26a30f2ac1..6e949e3c478d 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/rollup_fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/rollup_fixture_builder.nr @@ -3,7 +3,9 @@ use crate::abis::{ block_root_rollup_data::{BlockRootRollupBlobData, BlockRootRollupData}, previous_rollup_data::PreviousRollupData, }; -use blob::blob_public_inputs::{BlobCommitment, BlockBlobPublicInputs}; +use blob::blob_batching_public_inputs::{ + BatchingBlobCommitment, BlobAccumulatorPublicInputs, BLSPoint, FinalBlobBatchingChallenges, +}; use parity_lib::root::root_rollup_parity_input::RootRollupParityInput; use std::test::OracleMock; use types::{ @@ -22,7 +24,7 @@ use types::{ partial_state_reference::PartialStateReference, proof::vk_data::VkData, tests::{fixtures, merkle_tree_utils::{compute_zero_hashes, NonEmptyMerkleTree}}, - traits::{Empty, Hash}, + traits::{Empty, Hash, Serialize}, }; pub struct RollupFixtureBuilder { @@ -35,8 +37,10 @@ pub struct RollupFixtureBuilder { pub last_archive_sibling_path: [Field; ARCHIVE_HEIGHT], pub new_archive: AppendOnlyTreeSnapshot, pub new_archive_sibling_path: [Field; ARCHIVE_HEIGHT], + pub start_blob_accumulator: BlobAccumulatorPublicInputs, + pub final_blob_challenges: FinalBlobBatchingChallenges, pub blobs_fields: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], - pub blob_commitments: [BlobCommitment; BLOBS_PER_BLOCK], + pub blob_commitments: [BLSPoint; BLOBS_PER_BLOCK], pub blobs_hash: Field, pub vk_tree: MerkleTree, pub vk_tree_root: Field, @@ -63,8 +67,10 @@ impl RollupFixtureBuilder { last_archive_sibling_path: [0; ARCHIVE_HEIGHT], new_archive: AppendOnlyTreeSnapshot::zero(), new_archive_sibling_path: [0; ARCHIVE_HEIGHT], + start_blob_accumulator: BlobAccumulatorPublicInputs::empty(), + final_blob_challenges: FinalBlobBatchingChallenges::empty(), blobs_fields: [0; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], - blob_commitments: [BlobCommitment::empty(); BLOBS_PER_BLOCK], + blob_commitments: [BatchingBlobCommitment::empty().point; BLOBS_PER_BLOCK], blobs_hash: 0, vk_tree, vk_tree_root, @@ -169,7 +175,8 @@ impl RollupFixtureBuilder { self.blobs_fields[N + i] = blob_fields_1[i]; } - self.blob_commitments[0] = BlobCommitment { inner: [31, 75] }; + self.blob_commitments[0] = + BatchingBlobCommitment::from_limbs([31, 0, 0, 0], [75, 0, 0, 0]).point; self.blobs_hash = 8901; @@ -266,6 +273,8 @@ impl RollupFixtureBuilder { previous_archive_sibling_path: self.last_archive_sibling_path, new_archive_sibling_path: self.new_archive_sibling_path, previous_block_header: self.previous_block_header, + start_blob_accumulator: self.start_blob_accumulator, + final_blob_challenges: self.final_blob_challenges, prover_id: self.prover_id, } } @@ -278,10 +287,11 @@ impl RollupFixtureBuilder { } } - pub fn mock_evaluate_blobs(_self: Self) { + pub fn mock_evaluate_blobs_and_batch(_self: Self) { // Safety: Mock the oracle call when the blob data is not relevant to the test. unsafe { - let _ = OracleMock::mock("evaluateBlobs").returns(BlockBlobPublicInputs::empty()); + let _ = OracleMock::mock("evaluateBlobs").returns(BlobAccumulatorPublicInputs::empty() + .serialize()); } } } 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 1283e19ce45e..343069a144e7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -234,6 +234,10 @@ pub global BLS12_POINT_COMPRESSED_BYTES: u32 = 48; // TODO(MW): get this from bi pub global BLOB_ACCUMULATOR_PUBLIC_INPUTS: u32 = 3 /* v_acc, z_acc, and gamma_acc */ + 2 * BLS12_FR_LIMBS /* y_acc and gamma^i */ + BLS12_POINT /* c_acc */; +pub global FINAL_BLOB_ACCUMULATOR_PUBLIC_INPUTS: u32 = 1 /* blob_commitments_hash */ + + 1 /* z */ + + BLS12_FR_LIMBS /* y */ + + 2 /* c */; pub global BLOCK_BLOB_PUBLIC_INPUTS: u32 = 2 * BLOB_ACCUMULATOR_PUBLIC_INPUTS /* start and end accumulators */ + 1 /* z */ + BLS12_FR_LIMBS /* gamma */; @@ -462,8 +466,7 @@ pub global BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH: u32 = APPEND_ONLY_TRE + 1 /* vk_tree_root */ + 1 /* protocol_contract_tree_root */ + 1 /* prover_id */ - + BLOCK_BLOB_PUBLIC_INPUTS /* blob_public_inputs */ - + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK; + + BLOCK_BLOB_PUBLIC_INPUTS /* blob_public_inputs */; pub global ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH: u32 = 1 /* previous_archive_root */ + 1 /* end_archive_root */ + 1 /* chain_id */ @@ -473,7 +476,7 @@ pub global ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH: u32 = 1 /* previous_archive_root */ + 1 /* prover_id */ + AZTEC_MAX_EPOCH_DURATION /* proposedBlockHeaderHashes */ + AZTEC_MAX_EPOCH_DURATION * FEE_RECIPIENT_LENGTH /* fees */ - + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK; + + FINAL_BLOB_ACCUMULATOR_PUBLIC_INPUTS /* blob_public_inputs */; pub global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NOTE_HASHES_PER_TX; pub global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NULLIFIERS_PER_TX; pub global PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP: u32 =