diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 461b7364893e..1483b140a3bb 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -78,18 +78,16 @@ library Constants { uint256 internal constant PRIVATE_KERNEL_INNER_INDEX = 3; uint256 internal constant PRIVATE_KERNEL_TAIL_INDEX = 4; uint256 internal constant PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX = 5; - uint256 internal constant PUBLIC_KERNEL_MERGE_INDEX = 6; - uint256 internal constant PUBLIC_KERNEL_TAIL_INDEX = 7; - uint256 internal constant PUBLIC_KERNEL_INNER_INDEX = 8; + uint256 internal constant TUBE_VK_INDEX = 6; + uint256 internal constant PRIVATE_BASE_ROLLUP_VK_INDEX = 8; + uint256 internal constant PUBLIC_BASE_ROLLUP_VK_INDEX = 9; uint256 internal constant BASE_PARITY_INDEX = 10; uint256 internal constant ROOT_PARITY_INDEX = 11; - uint256 internal constant BASE_ROLLUP_INDEX = 12; - uint256 internal constant MERGE_ROLLUP_INDEX = 13; - uint256 internal constant BLOCK_ROOT_ROLLUP_INDEX = 14; - uint256 internal constant BLOCK_MERGE_ROLLUP_INDEX = 15; - uint256 internal constant ROOT_ROLLUP_INDEX = 16; - uint256 internal constant BLOCK_ROOT_ROLLUP_EMPTY_INDEX = 17; - uint256 internal constant TUBE_INDEX = 18; + uint256 internal constant MERGE_ROLLUP_INDEX = 12; + uint256 internal constant BLOCK_ROOT_ROLLUP_INDEX = 13; + uint256 internal constant BLOCK_MERGE_ROLLUP_INDEX = 14; + uint256 internal constant ROOT_ROLLUP_INDEX = 15; + uint256 internal constant BLOCK_ROOT_ROLLUP_EMPTY_INDEX = 16; uint256 internal constant PRIVATE_KERNEL_RESET_INDEX = 20; uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4; uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000000000; diff --git a/noir-projects/noir-protocol-circuits/Nargo.template.toml b/noir-projects/noir-protocol-circuits/Nargo.template.toml index 7cb2f3c88cea..22ca431a62f2 100644 --- a/noir-projects/noir-protocol-circuits/Nargo.template.toml +++ b/noir-projects/noir-protocol-circuits/Nargo.template.toml @@ -21,17 +21,16 @@ members = [ "crates/empty-nested", "crates/empty-nested-simulated", "crates/public-kernel-lib", - "crates/public-kernel-inner", "crates/public-kernel-inner-simulated", - "crates/public-kernel-merge", "crates/public-kernel-merge-simulated", - "crates/public-kernel-tail", "crates/public-kernel-tail-simulated", "crates/reset-kernel-lib", "crates/rollup-lib", "crates/rollup-merge", - "crates/rollup-base", - "crates/rollup-base-simulated", + "crates/rollup-base-private", + "crates/rollup-base-private-simulated", + "crates/rollup-base-public", + "crates/rollup-base-public-simulated", "crates/rollup-block-merge", "crates/rollup-block-root", "crates/rollup-block-root-empty", diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr index cb1b2edc1eaf..d334b5348c15 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr @@ -2,8 +2,8 @@ use crate::parity_public_inputs::ParityPublicInputs; use dep::types::{ constants::{BASE_PARITY_INDEX, VK_TREE_HEIGHT}, merkle_tree::membership::assert_check_membership, - recursion::{ - proof::RecursiveProof, + proof::{ + recursive_proof::RecursiveProof, traits::Verifiable, verification_key::{HonkVerificationKey, VerificationKey}, }, diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr index 4053d13743e5..2efb6023d567 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -60,7 +60,7 @@ mod tests { root::{root_parity_input::RootParityInput, root_parity_inputs::RootParityInputs}, }; use dep::types::constants::BASE_PARITY_INDEX; - use dep::types::recursion::{proof::RecursiveProof, verification_key::VerificationKey}; + use dep::types::proof::{recursive_proof::RecursiveProof, verification_key::VerificationKey}; use dep::types::tests::fixtures; use super::NUM_BASE_PARITY_PER_ROOT_PARITY; diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr index dc0c35e24546..cbb08eb2fe9a 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr @@ -2,8 +2,8 @@ use crate::parity_public_inputs::ParityPublicInputs; use dep::types::{ constants::{ROOT_PARITY_INDEX, VK_TREE_HEIGHT}, merkle_tree::membership::assert_check_membership, - recursion::{ - proof::NestedRecursiveProof, + proof::{ + recursive_proof::NestedRecursiveProof, traits::Verifiable, verification_key::{HonkVerificationKey, VerificationKey}, }, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr index f1042b6d9454..76ac505ad729 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr @@ -1,8 +1,8 @@ use dep::types::{ header::Header, KernelCircuitPublicInputs, - recursion::{ - proof::RecursiveProof, + proof::{ + recursive_proof::RecursiveProof, traits::Verifiable, verification_key::{HonkVerificationKey, VerificationKey}, }, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index b63f31ede3d5..0a67842e305b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -88,7 +88,7 @@ mod tests { }; use dep::types::{ abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - constants::{BASE_ROLLUP_INDEX, PRIVATE_KERNEL_INIT_INDEX}, + constants::{EMPTY_NESTED_INDEX, PRIVATE_KERNEL_INIT_INDEX}, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, }; @@ -170,7 +170,7 @@ mod tests { #[test(should_fail_with = "Invalid vk index")] fn invalid_previous_kernel() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + builder.previous_kernel = builder.previous_kernel.in_vk_tree(EMPTY_NESTED_INDEX); let _res = builder.execute(); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index 682c7a0a521b..17a7023c65c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -154,7 +154,7 @@ mod tests { utils::arrays::find_index_hint, }; use dep::types::constants::{ - BASE_ROLLUP_INDEX, GENERATOR_INDEX__OVSK_M, MAX_KEY_VALIDATION_REQUESTS_PER_TX, + EMPTY_NESTED_INDEX, GENERATOR_INDEX__OVSK_M, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, PRIVATE_KERNEL_INNER_INDEX, }; @@ -672,7 +672,7 @@ mod tests { #[test(should_fail_with = "Invalid vk index")] fn invalid_previous_kernel() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + builder.previous_kernel = builder.previous_kernel.in_vk_tree(EMPTY_NESTED_INDEX); let _res = builder.execute(); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 8e8268ad5b40..946609fd82c3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -65,7 +65,7 @@ mod tests { traits::is_empty, }; use dep::types::constants::{ - BASE_ROLLUP_INDEX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, GENERATOR_INDEX__IVSK_M, + DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, EMPTY_NESTED_INDEX, GENERATOR_INDEX__IVSK_M, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NULLIFIER, PRIVATE_KERNEL_INNER_INDEX, }; @@ -333,7 +333,7 @@ mod tests { #[test(should_fail_with = "Invalid vk index")] fn invalid_previous_kernel() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + builder.previous_kernel = builder.previous_kernel.in_vk_tree(EMPTY_NESTED_INDEX); let _res = builder.execute(); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 7910463a8000..60bbb8bb959d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -64,13 +64,13 @@ mod tests { nullifier::{Nullifier, ScopedNullifier}, }, address::{AztecAddress, EthAddress}, - constants::PRIVATE_KERNEL_INNER_INDEX, point::Point, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, }; use dep::types::constants::{ - DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, GENERATOR_INDEX__TSK_M, - L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, + DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, EMPTY_NESTED_INDEX, FIXED_AVM_STARTUP_L2_GAS, + GENERATOR_INDEX__TSK_M, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, + PRIVATE_KERNEL_INNER_INDEX, }; // TODO: Reduce the duplicated code/tests for PrivateKernelTailToPublicInputs and PrivateKernelTailInputs. @@ -420,10 +420,11 @@ mod tests { let _res = builder.execute(); } } - // #[test(should_fail_with = "Invalid vk index")] - // fn invalid_previous_kernel() { - // let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - // let _res = builder.execute(); - // } + + #[test(should_fail_with = "Invalid vk index")] + fn invalid_previous_kernel() { + let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); + builder.previous_kernel = builder.previous_kernel.in_vk_tree(EMPTY_NESTED_INDEX); + let _res = builder.execute(); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/Nargo.toml deleted file mode 100644 index 8455ddac0cea..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/Nargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "public_kernel_inner" -type = "bin" -authors = [""] -compiler_version = ">=0.18.0" - -[dependencies] -types = { path = "../types" } -public_kernel_lib = { path = "../public-kernel-lib" } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/src/main.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/src/main.nr deleted file mode 100644 index a19659b00de1..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-inner/src/main.nr +++ /dev/null @@ -1,7 +0,0 @@ -use dep::public_kernel_lib::PublicKernelInnerCircuitPrivateInputs; -use dep::types::VMCircuitPublicInputs; - -#[recursive] -fn main(input: PublicKernelInnerCircuitPrivateInputs) -> pub VMCircuitPublicInputs { - input.execute() -} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr index 26283872651b..0d54460ec3df 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr @@ -7,16 +7,13 @@ use crate::{ }, public_kernel_phase::PublicKernelPhase, }; -use dep::types::{ - abis::{ - enqueued_call_data::EnqueuedCallData, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - public_kernel_data::PublicKernelData, - }, - constants::{PUBLIC_KERNEL_MERGE_INDEX, TUBE_INDEX}, +use dep::types::abis::{ + enqueued_call_data::EnqueuedCallData, + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + public_kernel_data::PublicKernelData, }; -global ALLOWED_PREVIOUS_CIRCUITS = [TUBE_INDEX, PUBLIC_KERNEL_MERGE_INDEX]; +global ALLOWED_PREVIOUS_CIRCUITS = []; pub struct PublicKernelMergeCircuitPrivateInputs { previous_kernel: PublicKernelData, @@ -61,12 +58,11 @@ impl PublicKernelMergeCircuitPrivateInputs { phase, ); - let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel); - previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); - + // let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel); + // previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); let enqueued_call_data_validator = EnqueuedCallDataValidator::new(self.enqueued_call, phase); - enqueued_call_data_validator.validate_proof(); + // enqueued_call_data_validator.validate_proof(); enqueued_call_data_validator.validate_against_previous_kernel( self.previous_kernel.public_inputs, output_validator.previous_validation_request_array_lengths, @@ -92,7 +88,6 @@ mod tests { max_block_number::MaxBlockNumber, validation_requests::PublicValidationRequestArrayLengths, }, - constants::{BASE_ROLLUP_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX}, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, }; @@ -105,9 +100,7 @@ mod tests { impl PublicKernelMergeCircuitPrivateInputsBuilder { pub fn new() -> Self { - let previous_kernel = FixtureBuilder::new().as_parent_contract().in_vk_tree( - PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - ); + let previous_kernel = FixtureBuilder::new().as_parent_contract(); let mut previous_revertible = FixtureBuilder::new(); let mut enqueued_call = FixtureBuilder::new().is_public_function(); // Add an offset so that the mock data won't be the same as the values in previous_kernel. @@ -253,21 +246,4 @@ mod tests { assert_eq(output.end_non_revertible.gas_used, Gas::new(200, 200)); assert_eq(output.end.gas_used, Gas::new(350, 350)); } - - #[test] - fn valid_previous_kernel() { - for i in 0..ALLOWED_PREVIOUS_CIRCUITS.len() { - let mut builder = PublicKernelMergeCircuitPrivateInputsBuilder::new(); - builder.previous_kernel = - builder.previous_kernel.in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS[i]); - builder.succeeded(); - } - } - - #[test(should_fail_with = "Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelMergeCircuitPrivateInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - let _res = builder.execute(); - } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 6f28560c91e7..96e3f7c0022d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -24,13 +24,12 @@ use dep::types::{ L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_TX, NOTE_HASH_TREE_HEIGHT, - PUBLIC_KERNEL_MERGE_INDEX, }, data::PublicDataLeafHint, partial_state_reference::PartialStateReference, }; -global ALLOWED_PREVIOUS_CIRCUITS = [PUBLIC_KERNEL_MERGE_INDEX]; +global ALLOWED_PREVIOUS_CIRCUITS = []; pub struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, @@ -65,8 +64,7 @@ impl PublicKernelTailCircuitPrivateInputs { pub fn execute(self) -> KernelCircuitPublicInputs { let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel); previous_kernel_validator.validate_phase(PublicKernelPhase.TAIL); - previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); - + // previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); let (output, output_hints, public_data_read_request_hints) = unsafe { self.generate_output_and_hints() }; @@ -114,14 +112,14 @@ mod tests { }, address::AztecAddress, constants::{ - BASE_ROLLUP_INDEX, L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, + L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, - PUBLIC_DATA_TREE_HEIGHT, PUBLIC_KERNEL_MERGE_INDEX, + PUBLIC_DATA_TREE_HEIGHT, }, data::{PublicDataLeafHint, PublicDataTreeLeafPreimage}, hash::{compute_siloed_nullifier, silo_note_hash}, @@ -191,7 +189,7 @@ mod tests { impl PublicKernelTailCircuitPrivateInputsBuilder { pub fn new() -> PublicKernelTailCircuitPrivateInputsBuilder { - let previous_kernel = FixtureBuilder::new().in_vk_tree(PUBLIC_KERNEL_MERGE_INDEX); + let previous_kernel = FixtureBuilder::new(); let previous_revertible = FixtureBuilder::new(); let nullifier_non_existent_read_request_hints_builder = NullifierNonExistentReadRequestHintsBuilder::new(); @@ -703,19 +701,4 @@ mod tests { .map(|n: ScopedNullifier| n.nullifier.value); assert_array_eq(public_inputs.end.nullifiers, expected); } - - #[test] - fn valid_previous_kernel_merge() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(PUBLIC_KERNEL_MERGE_INDEX); - - let _res = builder.execute(); - } - - #[test(should_fail_with = "Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - let _res = builder.execute(); - } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-merge/src/main.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-merge/src/main.nr deleted file mode 100644 index 4a4a7f036bf3..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-merge/src/main.nr +++ /dev/null @@ -1,7 +0,0 @@ -use dep::public_kernel_lib::PublicKernelMergeCircuitPrivateInputs; -use dep::types::PublicKernelCircuitPublicInputs; - -#[recursive] -fn main(input: PublicKernelMergeCircuitPrivateInputs) -> pub PublicKernelCircuitPublicInputs { - input.execute() -} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-tail/src/main.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-tail/src/main.nr deleted file mode 100644 index a777bdad4010..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-tail/src/main.nr +++ /dev/null @@ -1,7 +0,0 @@ -use dep::public_kernel_lib::PublicKernelTailCircuitPrivateInputs; -use dep::types::KernelCircuitPublicInputs; - -#[recursive] -fn main(input: PublicKernelTailCircuitPrivateInputs) -> pub KernelCircuitPublicInputs { - input.execute() -} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-tail/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/Nargo.toml similarity index 58% rename from noir-projects/noir-protocol-circuits/crates/public-kernel-tail/Nargo.toml rename to noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/Nargo.toml index 9071a4db2acb..b2f0e7649d9d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-tail/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/Nargo.toml @@ -1,9 +1,9 @@ [package] -name = "public_kernel_tail" +name = "rollup_base_private_simulated" type = "bin" authors = [""] compiler_version = ">=0.18.0" [dependencies] +rollup_lib = { path = "../rollup-lib" } types = { path = "../types" } -public_kernel_lib = { path = "../public-kernel-lib" } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/src/main.nr new file mode 100644 index 000000000000..e2093b6e0c98 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-private-simulated/src/main.nr @@ -0,0 +1,6 @@ +use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, PrivateBaseRollupInputs}; + +#[recursive] +unconstrained fn main(inputs: PrivateBaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { + inputs.execute() +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-base-private/Nargo.toml similarity index 83% rename from noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/Nargo.toml rename to noir-projects/noir-protocol-circuits/crates/rollup-base-private/Nargo.toml index cda6dfa73c57..76f1c14e1b42 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-private/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "rollup_base_simulated" +name = "rollup_base_private" type = "bin" authors = [""] compiler_version = ">=0.18.0" diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-private/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base-private/src/main.nr new file mode 100644 index 000000000000..c6dea8ed5bc9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-private/src/main.nr @@ -0,0 +1,6 @@ +use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, PrivateBaseRollupInputs}; + +#[recursive] +fn main(inputs: PrivateBaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { + inputs.execute() +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-merge/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/Nargo.toml similarity index 57% rename from noir-projects/noir-protocol-circuits/crates/public-kernel-merge/Nargo.toml rename to noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/Nargo.toml index c6433b119986..d92f4e9cb804 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-merge/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/Nargo.toml @@ -1,9 +1,9 @@ [package] -name = "public_kernel_merge" +name = "rollup_base_public_simulated" type = "bin" authors = [""] compiler_version = ">=0.18.0" [dependencies] +rollup_lib = { path = "../rollup-lib" } types = { path = "../types" } -public_kernel_lib = { path = "../public-kernel-lib" } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/src/main.nr new file mode 100644 index 000000000000..57a1b92ab029 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-public-simulated/src/main.nr @@ -0,0 +1,6 @@ +use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, PublicBaseRollupInputs}; + +#[recursive] +unconstrained fn main(inputs: PublicBaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { + inputs.execute() +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Nargo.toml similarity index 84% rename from noir-projects/noir-protocol-circuits/crates/rollup-base/Nargo.toml rename to noir-projects/noir-protocol-circuits/crates/rollup-base-public/Nargo.toml index 5e80ccb69e39..a148c4cc7aa2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-base/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "rollup_base" +name = "rollup_base_public" type = "bin" authors = [""] compiler_version = ">=0.18.0" diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-public/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/src/main.nr new file mode 100644 index 000000000000..30aad3b7dafd --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/src/main.nr @@ -0,0 +1,6 @@ +use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, PublicBaseRollupInputs}; + +#[recursive] +fn main(inputs: PublicBaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { + inputs.execute() +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/src/main.nr deleted file mode 100644 index 0ff893873e47..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/rollup-base-simulated/src/main.nr +++ /dev/null @@ -1,5 +0,0 @@ -use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, BaseRollupInputs}; - -unconstrained fn main(inputs: BaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { - inputs.base_rollup_circuit() -} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base/src/main.nr b/noir-projects/noir-protocol-circuits/crates/rollup-base/src/main.nr deleted file mode 100644 index 19ea63d649a5..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/rollup-base/src/main.nr +++ /dev/null @@ -1,6 +0,0 @@ -use dep::rollup_lib::base::{BaseOrMergeRollupPublicInputs, BaseRollupInputs}; - -#[recursive] -fn main(inputs: BaseRollupInputs) -> pub BaseOrMergeRollupPublicInputs { - inputs.base_rollup_circuit() -} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr index 3a9c2ab9f02b..6c2297ce3679 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr @@ -2,8 +2,8 @@ use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergeP use dep::types::{ constants::VK_TREE_HEIGHT, merkle_tree::{membership::assert_check_membership, MembershipWitness}, - recursion::{ - proof::NestedRecursiveProof, + proof::{ + recursive_proof::NestedRecursiveProof, traits::Verifiable, verification_key::{HonkVerificationKey, VerificationKey}, }, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index a9e771d19d1d..a796a128fdbf 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -2,8 +2,8 @@ use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInpu use dep::types::{ constants::VK_TREE_HEIGHT, merkle_tree::{membership::assert_check_membership, MembershipWitness}, - recursion::{ - proof::NestedRecursiveProof, + proof::{ + recursive_proof::NestedRecursiveProof, traits::Verifiable, verification_key::{HonkVerificationKey, VerificationKey}, }, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 4b74c94aa43f..498924d2a6d4 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -8,7 +8,8 @@ use crate::{ }; use dep::types::{ abis::{ - append_only_tree_snapshot::AppendOnlyTreeSnapshot, kernel_data::KernelData, + append_only_tree_snapshot::AppendOnlyTreeSnapshot, + kernel_circuit_public_inputs::KernelCircuitPublicInputs, nullifier_leaf_preimage::NullifierLeafPreimage, public_data_update_request::PublicDataUpdateRequest, }, @@ -18,8 +19,7 @@ use dep::types::{ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PRIVATE_KERNEL_EMPTY_INDEX, PUBLIC_DATA_SUBTREE_HEIGHT, - PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, PUBLIC_KERNEL_TAIL_INDEX, - TUBE_INDEX, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, }, data::{ hash::{compute_public_data_tree_index, compute_public_data_tree_value}, @@ -39,8 +39,10 @@ use dep::types::{ utils::field::{full_field_greater_than, full_field_less_than}, }; -global ALLOWED_PREVIOUS_CIRCUITS = - [PRIVATE_KERNEL_EMPTY_INDEX, TUBE_INDEX, PUBLIC_KERNEL_TAIL_INDEX]; +// Temporary struct to avoid changing all the references to kernel_data. Will remove it and just pass in the public_inputs. +struct KernelData { + public_inputs: KernelCircuitPublicInputs, +} pub struct BaseRollupInputs { kernel_data: KernelData, @@ -63,11 +65,6 @@ pub struct BaseRollupInputs { impl BaseRollupInputs { pub fn base_rollup_circuit(self) -> BaseOrMergeRollupPublicInputs { - if !dep::std::runtime::is_unconstrained() { - // Recursively verify the tube proof if straight from private, or the public kernel tail - self.kernel_data.verify(); - self.kernel_data.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); - } // Verify the kernel chain_id and versions assert( self.kernel_data.public_inputs.constants.tx_context.chain_id @@ -512,28 +509,28 @@ mod tests { constant_rollup_data::ConstantRollupData, }, base::{ - base_rollup_inputs::{BaseRollupInputs, compute_fee_payer_fee_juice_balance_leaf_slot}, + base_rollup_inputs::{ + BaseRollupInputs, compute_fee_payer_fee_juice_balance_leaf_slot, KernelData, + }, state_diff_hints::StateDiffHints, }, components::TX_EFFECTS_HASH_INPUT_FIELDS, }; use dep::types::{ abis::{ - append_only_tree_snapshot::AppendOnlyTreeSnapshot, kernel_data::KernelData, + append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage, public_data_update_request::PublicDataUpdateRequest, }, address::{AztecAddress, EthAddress}, constants::{ - ARCHIVE_HEIGHT, BASE_ROLLUP_INDEX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, - NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, + ARCHIVE_HEIGHT, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, - PUBLIC_KERNEL_TAIL_INDEX, TUBE_INDEX, }, data::{public_data_hint::PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, hash::silo_l2_to_l1_message, @@ -800,7 +797,8 @@ mod tests { } unconstrained fn build_inputs(mut self) -> BaseRollupInputs { - let mut kernel_data = self.kernel_data.to_kernel_data(); + let mut kernel_data = + KernelData { public_inputs: self.kernel_data.to_kernel_circuit_public_inputs() }; let start_note_hash_tree = NonEmptyMerkleTree::new( self.pre_existing_notes, @@ -1484,26 +1482,4 @@ mod tests { let _res = builder.execute(); } - - #[test] - fn valid_previous_kernel_tube() { - let builder = unsafe { BaseRollupInputsBuilder::new_with_previous_kernel(TUBE_INDEX) }; - - let _res = builder.execute(); - } - - #[test] - fn valid_previous_kernel_public_tail() { - let builder = - unsafe { BaseRollupInputsBuilder::new_with_previous_kernel(PUBLIC_KERNEL_TAIL_INDEX) }; - - let _res = builder.execute(); - } - - #[test(should_fail_with = "Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = BaseRollupInputsBuilder::new(); - builder.kernel_data = builder.kernel_data.in_vk_tree(BASE_ROLLUP_INDEX); - let _res = builder.execute(); - } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr new file mode 100644 index 000000000000..43bc6b18dfb2 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr @@ -0,0 +1,17 @@ +use dep::types::{ + abis::kernel_circuit_public_inputs::vm_circuit_public_inputs::VMCircuitPublicInputs, + constants::AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, + proof::{avm_proof::AvmProof, traits::Verifiable, vk_data::VkData}, +}; + +pub struct AvmProofData { + public_inputs: VMCircuitPublicInputs, + proof: AvmProof, + vk_data: VkData, +} + +impl Verifiable for AvmProofData { + fn verify(self) { + // TODO(#8470) + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/mod.nr new file mode 100644 index 000000000000..c998111d9a63 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/mod.nr @@ -0,0 +1,3 @@ +pub mod avm_proof_data; +pub mod private_tube_data; +pub mod public_tube_data; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/private_tube_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/private_tube_data.nr new file mode 100644 index 000000000000..74eac402aee7 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/private_tube_data.nr @@ -0,0 +1,23 @@ +use dep::types::{ + abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, + constants::HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + proof::{traits::Verifiable, tube_proof::TubeProof, vk_data::VkData}, +}; + +pub struct PrivateTubeData { + public_inputs: KernelCircuitPublicInputs, + proof: TubeProof, + vk_data: VkData, +} + +impl Verifiable for PrivateTubeData { + fn verify(self) { + let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); + std::verify_proof( + self.vk_data.vk.key, + self.proof.fields, + inputs, + self.vk_data.vk.hash, + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr new file mode 100644 index 000000000000..cf0fe7d33003 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr @@ -0,0 +1,23 @@ +use dep::types::{ + abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, + constants::HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + proof::{traits::Verifiable, tube_proof::TubeProof, vk_data::VkData}, +}; + +pub struct PublicTubeData { + public_inputs: KernelCircuitPublicInputs, // TODO: This should be the output of private-kernel-tail-to-public. + proof: TubeProof, + vk_data: VkData, +} + +impl Verifiable for PublicTubeData { + fn verify(self) { + let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); + std::verify_proof( + self.vk_data.vk.key, + self.proof.fields, + inputs, + self.vk_data.vk.hash, + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr index 89b645952b3b..6bee28884ee5 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr @@ -1,5 +1,9 @@ mod base_rollup_inputs; +mod components; +mod private_base_rollup; +mod public_base_rollup; mod state_diff_hints; pub use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; -pub use base_rollup_inputs::BaseRollupInputs; +pub use private_base_rollup::PrivateBaseRollupInputs; +pub use public_base_rollup::PublicBaseRollupInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr new file mode 100644 index 000000000000..07eb8498ff6d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr @@ -0,0 +1,63 @@ +use crate::{ + abis::{ + base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs, + constant_rollup_data::ConstantRollupData, + }, + base::{ + base_rollup_inputs::{BaseRollupInputs, KernelData}, + components::private_tube_data::PrivateTubeData, + state_diff_hints::StateDiffHints, + }, +}; +use dep::types::{ + constants::{ + ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PRIVATE_KERNEL_EMPTY_INDEX, + PUBLIC_DATA_TREE_HEIGHT, TUBE_VK_INDEX, + }, + data::{public_data_hint::PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, + merkle_tree::MembershipWitness, + partial_state_reference::PartialStateReference, +}; + +global ALLOWED_PREVIOUS_CIRCUITS = [PRIVATE_KERNEL_EMPTY_INDEX, TUBE_VK_INDEX]; + +pub struct PrivateBaseRollupInputs { + tube_data: PrivateTubeData, + + start: PartialStateReference, + + state_diff_hints: StateDiffHints, + fee_payer_fee_juice_balance_read_hint: PublicDataHint, + + sorted_public_data_writes: [PublicDataTreeLeaf; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + sorted_public_data_writes_indexes: [u32; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_preimages: [PublicDataTreeLeafPreimage; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_witnesses: [MembershipWitness; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + + archive_root_membership_witness: MembershipWitness, + constants: ConstantRollupData, +} + +impl PrivateBaseRollupInputs { + pub fn execute(self) -> BaseOrMergeRollupPublicInputs { + if !dep::std::runtime::is_unconstrained() { + self.tube_data.verify(); + // TODO(#7410) + // self.tube_data.vk_data.validate_in_vk_tree(self.tube_data.public_inputs.constants.vk_tree_root, ALLOWED_PREVIOUS_CIRCUITS); + } + + BaseRollupInputs { + kernel_data: KernelData { public_inputs: self.tube_data.public_inputs }, + start: self.start, + state_diff_hints: self.state_diff_hints, + fee_payer_fee_juice_balance_read_hint: self.fee_payer_fee_juice_balance_read_hint, + sorted_public_data_writes: self.sorted_public_data_writes, + sorted_public_data_writes_indexes: self.sorted_public_data_writes_indexes, + low_public_data_writes_preimages: self.low_public_data_writes_preimages, + low_public_data_writes_witnesses: self.low_public_data_writes_witnesses, + archive_root_membership_witness: self.archive_root_membership_witness, + constants: self.constants, + } + .base_rollup_circuit() + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr new file mode 100644 index 000000000000..08fc35076bf2 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -0,0 +1,66 @@ +use crate::{ + abis::{ + base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs, + constant_rollup_data::ConstantRollupData, + }, + base::{ + base_rollup_inputs::{BaseRollupInputs, KernelData}, + components::{avm_proof_data::AvmProofData, public_tube_data::PublicTubeData}, + state_diff_hints::StateDiffHints, + }, +}; +use dep::types::{ + constants::{ + ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, + TUBE_VK_INDEX, + }, + data::{public_data_hint::PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, + merkle_tree::MembershipWitness, + partial_state_reference::PartialStateReference, +}; + +pub struct PublicBaseRollupInputs { + tube_data: PublicTubeData, + avm_proof_data: AvmProofData, + + start: PartialStateReference, + + state_diff_hints: StateDiffHints, + fee_payer_fee_juice_balance_read_hint: PublicDataHint, + + sorted_public_data_writes: [PublicDataTreeLeaf; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + sorted_public_data_writes_indexes: [u32; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_preimages: [PublicDataTreeLeafPreimage; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_witnesses: [MembershipWitness; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + + archive_root_membership_witness: MembershipWitness, + constants: ConstantRollupData, +} + +impl PublicBaseRollupInputs { + pub fn execute(self) -> BaseOrMergeRollupPublicInputs { + // Skip it for now. As we currently swap the public inputs to be the output of public tail, so the proof won't be verfied. + // if !dep::std::runtime::is_unconstrained() { + // self.tube_data.verify(); + // self.tube_data.vk_data.validate_in_vk_tree([TUBE_VK_INDEX]); + // } + // TODO(#8470) + // if !dep::std::runtime::is_unconstrained() { + // self.avm_proof_data.verify(); + // self.avm_proof_data.vk_data.validate_in_vk_tree([AVM_VK_INDEX]); + // } + BaseRollupInputs { + kernel_data: KernelData { public_inputs: self.tube_data.public_inputs }, + start: self.start, + state_diff_hints: self.state_diff_hints, + fee_payer_fee_juice_balance_read_hint: self.fee_payer_fee_juice_balance_read_hint, + sorted_public_data_writes: self.sorted_public_data_writes, + sorted_public_data_writes_indexes: self.sorted_public_data_writes_indexes, + low_public_data_writes_preimages: self.low_public_data_writes_preimages, + low_public_data_writes_witnesses: self.low_public_data_writes_witnesses, + archive_root_membership_witness: self.archive_root_membership_witness, + constants: self.constants, + } + .base_rollup_circuit() + } +} 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 845d5b056ea8..fc2c8e70d713 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 @@ -9,9 +9,10 @@ use parity_lib::root::root_rollup_parity_input::RootRollupParityInput; use types::{ abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::{ - ARCHIVE_HEIGHT, AZTEC_EPOCH_DURATION, BASE_ROLLUP_INDEX, L1_TO_L2_MSG_SUBTREE_HEIGHT, + ARCHIVE_HEIGHT, AZTEC_EPOCH_DURATION, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, MERGE_ROLLUP_INDEX, - NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_BASE_ROLLUP_VK_INDEX, + PUBLIC_BASE_ROLLUP_VK_INDEX, }, content_commitment::ContentCommitment, header::Header, @@ -21,7 +22,8 @@ use types::{ }; use types::debug_log::debug_log_format; -global ALLOWED_PREVIOUS_CIRCUITS = [BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX]; +global ALLOWED_PREVIOUS_CIRCUITS = + [MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, PUBLIC_BASE_ROLLUP_VK_INDEX]; pub struct BlockRootRollupInputs { // All below are shared between the base and merge rollups diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index 8994feaba8fb..c23386096729 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -3,9 +3,13 @@ use crate::abis::base_or_merge_rollup_public_inputs::{ }; use crate::abis::previous_rollup_data::PreviousRollupData; use crate::components; -use dep::types::{constants::{BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX}, traits::Empty}; +use dep::types::{ + constants::{MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, PUBLIC_BASE_ROLLUP_VK_INDEX}, + traits::Empty, +}; -global ALLOWED_PREVIOUS_CIRCUITS = [BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX]; +global ALLOWED_PREVIOUS_CIRCUITS = + [MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, PUBLIC_BASE_ROLLUP_VK_INDEX]; pub struct MergeRollupInputs { // TODO(Kev): Why is this 2? @@ -61,7 +65,9 @@ impl MergeRollupInputs { mod tests { use crate::tests::merge_rollup_inputs::default_merge_rollup_inputs; - use dep::types::constants::{BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX, ROOT_PARITY_INDEX}; + use dep::types::constants::{ + MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, ROOT_PARITY_INDEX, + }; use dep::types::hash::accumulate_sha256; use types::merkle_tree::merkle_tree::MerkleTree; use types::tests::fixtures; @@ -190,10 +196,11 @@ mod tests { comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(BASE_ROLLUP_INDEX); - inputs.previous_rollup_data[0].vk_witness.leaf_index = BASE_ROLLUP_INDEX as Field; + fixtures::vk_tree::generate_fake_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX); + inputs.previous_rollup_data[0].vk_witness.leaf_index = + PRIVATE_BASE_ROLLUP_VK_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = - vk_tree.get_sibling_path(BASE_ROLLUP_INDEX); + vk_tree.get_sibling_path(PRIVATE_BASE_ROLLUP_VK_INDEX); let _outputs = inputs.merge_rollup_circuit(); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index aac3ffd73d40..962ff736dfae 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -1,7 +1,7 @@ use crate::abis::base_or_merge_rollup_public_inputs::BASE_ROLLUP_TYPE; use crate::abis::previous_rollup_data::PreviousRollupData; use dep::types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot; -use dep::types::constants::BASE_ROLLUP_INDEX; +use dep::types::constants::PUBLIC_BASE_ROLLUP_VK_INDEX; use dep::types::merkle_tree::MembershipWitness; use dep::types::tests::fixtures; use types::merkle_tree::merkle_tree::MerkleTree; @@ -9,7 +9,7 @@ use types::merkle_tree::merkle_tree::MerkleTree; pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { let mut previous_rollup_data = [PreviousRollupData::empty(); 2]; - let vk_index = BASE_ROLLUP_INDEX; + let vk_index = PUBLIC_BASE_ROLLUP_VK_INDEX; let vk_tree: MerkleTree = comptime { fixtures::vk_tree::get_vk_merkle_tree() }; let vk_path = vk_tree.get_sibling_path(vk_index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr deleted file mode 100644 index ba83686a0a88..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr +++ /dev/null @@ -1,46 +0,0 @@ -use crate::{ - abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, - constants::{TUBE_INDEX, VK_TREE_HEIGHT}, - merkle_tree::membership::check_membership, - recursion::{ - proof::NestedRecursiveProof, traits::Verifiable, verification_key::HonkVerificationKey, - }, - utils::arrays::find_index_hint, -}; - -pub struct KernelData { - public_inputs: KernelCircuitPublicInputs, - proof: NestedRecursiveProof, - vk: HonkVerificationKey, - vk_index: u32, - vk_path: [Field; VK_TREE_HEIGHT], -} - -impl Verifiable for KernelData { - fn verify(self) { - let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); - std::verify_proof(self.vk.key, self.proof.fields, inputs, self.vk.hash); - } -} - -impl KernelData { - fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { - self.vk.check_hash(); - - let index_hint = - unsafe { find_index_hint(allowed_indices, |index: u32| index == self.vk_index) }; - assert(index_hint < N, "Invalid vk index"); - assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index"); - - // TODO(#7410) Remove the exception for the tube index - assert( - check_membership( - self.vk.hash, - self.vk_index as Field, - self.vk_path, - self.public_inputs.constants.vk_tree_root, - ) - | (self.vk_index == TUBE_INDEX), - ); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr index 6669bfeee5c6..aa6e2fb940c9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr @@ -29,7 +29,6 @@ mod max_block_number; pub mod private_kernel; pub mod kernel_circuit_public_inputs; -mod kernel_data; pub mod private_kernel_data; mod public_kernel_data; mod public_kernel_inner_data; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index 459aeab8bd25..5b3941764c0a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -3,8 +3,8 @@ use crate::{ address::SaltedInitializationHash, constants::{FUNCTION_TREE_HEIGHT, PROTOCOL_CONTRACT_TREE_HEIGHT}, merkle_tree::membership::MembershipWitness, + proof::verification_key::ClientIVCVerificationKey, public_keys::PublicKeys, - recursion::verification_key::ClientIVCVerificationKey, }; pub struct PrivateCallData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index 4a8f350de4ae..62942a62da93 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -2,7 +2,7 @@ use crate::{ abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, constants::{PRIVATE_KERNEL_RESET_INDEX, VK_TREE_HEIGHT}, merkle_tree::membership::assert_check_membership, - recursion::verification_key::ClientIVCVerificationKey, + proof::verification_key::ClientIVCVerificationKey, utils::arrays::find_index_hint, }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr index c8e8a15d35ee..8e86512fafd8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr @@ -1,9 +1,10 @@ use crate::{ abis::kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - constants::{TUBE_INDEX, VK_TREE_HEIGHT}, + constants::{TUBE_VK_INDEX, VK_TREE_HEIGHT}, merkle_tree::membership::check_membership, - recursion::{ - proof::NestedRecursiveProof, traits::Verifiable, verification_key::HonkVerificationKey, + proof::{ + recursive_proof::NestedRecursiveProof, traits::Verifiable, + verification_key::HonkVerificationKey, }, utils::arrays::find_index_hint, }; @@ -40,7 +41,7 @@ impl PublicKernelData { self.vk_path, self.public_inputs.constants.vk_tree_root, ) - | (self.vk_index == TUBE_INDEX), + | (self.vk_index == TUBE_VK_INDEX), ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_inner_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_inner_data.nr index 1b4977af0322..b397965bf2cb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_inner_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_inner_data.nr @@ -1,7 +1,8 @@ use crate::{ abis::kernel_circuit_public_inputs::VMCircuitPublicInputs, - recursion::{ - proof::NestedRecursiveProof, traits::Verifiable, verification_key::HonkVerificationKey, + proof::{ + recursive_proof::NestedRecursiveProof, traits::Verifiable, + verification_key::HonkVerificationKey, }, }; 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 8c605c074b17..143f86b82ae2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -111,18 +111,17 @@ comptime global PRIVATE_KERNEL_INIT_INDEX: u32 = 2; comptime global PRIVATE_KERNEL_INNER_INDEX: u32 = 3; comptime global PRIVATE_KERNEL_TAIL_INDEX: u32 = 4; comptime global PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX: u32 = 5; -comptime global PUBLIC_KERNEL_MERGE_INDEX: u32 = 6; -comptime global PUBLIC_KERNEL_TAIL_INDEX: u32 = 7; -comptime global PUBLIC_KERNEL_INNER_INDEX: u32 = 8; // TODO(#7124): To be deprecated. +comptime global TUBE_VK_INDEX: u32 = 6; +comptime global AVM_VK_INDEX: u32 = 7; +comptime global PRIVATE_BASE_ROLLUP_VK_INDEX: u32 = 8; +comptime global PUBLIC_BASE_ROLLUP_VK_INDEX: u32 = 9; comptime global BASE_PARITY_INDEX: u32 = 10; comptime global ROOT_PARITY_INDEX: u32 = 11; -comptime global BASE_ROLLUP_INDEX: u32 = 12; -comptime global MERGE_ROLLUP_INDEX: u32 = 13; -comptime global BLOCK_ROOT_ROLLUP_INDEX: u32 = 14; -comptime global BLOCK_MERGE_ROLLUP_INDEX: u32 = 15; -comptime global ROOT_ROLLUP_INDEX: u32 = 16; -comptime global BLOCK_ROOT_ROLLUP_EMPTY_INDEX: u32 = 17; -comptime global TUBE_INDEX: u32 = 18; +comptime global MERGE_ROLLUP_INDEX: u32 = 12; +comptime global BLOCK_ROOT_ROLLUP_INDEX: u32 = 13; +comptime global BLOCK_MERGE_ROLLUP_INDEX: u32 = 14; +comptime global ROOT_ROLLUP_INDEX: u32 = 15; +comptime global BLOCK_ROOT_ROLLUP_EMPTY_INDEX: u32 = 16; comptime global PRIVATE_KERNEL_RESET_INDEX: u32 = 20; // Important: Do not define indexes after the PRIVATE_KERNEL_RESET_INDEX. They are allocated for the variants of private kernel reset. diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 7ceb2ba0b6e8..5de0d2cf0f30 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -14,7 +14,7 @@ use crate::{ }, merkle_tree::root::root_from_sibling_path, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, - recursion::verification_key::VerificationKey, + proof::verification_key::VerificationKey, traits::{is_empty, ToField}, utils::field::field_from_bytes_32_trunc, }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 4fa82de35ff7..75345c071afe 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -25,8 +25,7 @@ mod tests; mod state_reference; mod partial_state_reference; - -mod recursion; +pub mod proof; mod data; mod storage; mod validate; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/avm_proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/avm_proof.nr new file mode 100644 index 000000000000..a7085739062c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/avm_proof.nr @@ -0,0 +1,37 @@ +use crate::{constants::AVM_PROOF_LENGTH_IN_FIELDS, traits::{Deserialize, Empty, Serialize}}; + +pub struct AvmProof { + fields: [Field; AVM_PROOF_LENGTH_IN_FIELDS], +} + +impl Serialize for AvmProof { + fn serialize(self) -> [Field; AVM_PROOF_LENGTH_IN_FIELDS] { + self.fields + } +} + +impl Deserialize for AvmProof { + fn deserialize(fields: [Field; AVM_PROOF_LENGTH_IN_FIELDS]) -> Self { + AvmProof { fields } + } +} + +impl Empty for AvmProof { + fn empty() -> Self { + AvmProof { fields: [0; AVM_PROOF_LENGTH_IN_FIELDS] } + } +} + +impl Eq for AvmProof { + fn eq(self, other: Self) -> bool { + (self.fields == other.fields) + } +} + +#[test] +fn serialization_of_empty_recursive() { + let item = AvmProof::empty(); + let serialized = item.serialize(); + let deserialized = AvmProof::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr new file mode 100644 index 000000000000..dd8befa88342 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr @@ -0,0 +1,6 @@ +pub mod avm_proof; +pub mod recursive_proof; +pub mod traits; +pub mod tube_proof; +pub mod verification_key; +pub mod vk_data; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/recursion/proof.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/traits.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/traits.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/recursion/traits.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/proof/traits.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr new file mode 100644 index 000000000000..370f28d95de8 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr @@ -0,0 +1,37 @@ +use crate::{constants::TUBE_PROOF_LENGTH, traits::{Deserialize, Empty, Serialize}}; + +pub struct TubeProof { + fields: [Field; TUBE_PROOF_LENGTH], +} + +impl Serialize for TubeProof { + fn serialize(self) -> [Field; TUBE_PROOF_LENGTH] { + self.fields + } +} + +impl Deserialize for TubeProof { + fn deserialize(fields: [Field; TUBE_PROOF_LENGTH]) -> Self { + TubeProof { fields } + } +} + +impl Empty for TubeProof { + fn empty() -> Self { + TubeProof { fields: [0; TUBE_PROOF_LENGTH] } + } +} + +impl Eq for TubeProof { + fn eq(self, other: Self) -> bool { + (self.fields == other.fields) + } +} + +#[test] +fn serialization_of_empty_recursive() { + let item = TubeProof::empty(); + let serialized = item.serialize(); + let deserialized = TubeProof::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr similarity index 77% rename from noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr index a11b7852902c..855a74393cc5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr @@ -1,6 +1,7 @@ use crate::{ constants::{ - CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, + HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, }, traits::{Deserialize, Empty, Serialize}, }; @@ -50,8 +51,9 @@ impl Eq for VerificationKey { } } -type HonkVerificationKey = VerificationKey; -type ClientIVCVerificationKey = VerificationKey; +pub type HonkVerificationKey = VerificationKey; +pub type ClientIVCVerificationKey = VerificationKey; +pub type AVMVerificationKey = VerificationKey; #[test] fn serialization_of_empty() { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr new file mode 100644 index 000000000000..7a62eddd4a36 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr @@ -0,0 +1,29 @@ +use crate::{ + constants::VK_TREE_HEIGHT, merkle_tree::membership::assert_check_membership, + utils::arrays::find_index_hint, +}; +use super::verification_key::VerificationKey; + +pub struct VkData { + vk: VerificationKey, + vk_index: u32, + vk_path: [Field; VK_TREE_HEIGHT], +} + +impl VkData { + pub fn validate_in_vk_tree(self, vk_tree_root: Field, allowed_indices: [u32; N]) { + self.vk.check_hash(); + + let index_hint = + unsafe { find_index_hint(allowed_indices, |index: u32| index == self.vk_index) }; + assert(index_hint < N, "Invalid vk index"); + assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index"); + + assert_check_membership( + self.vk.hash, + self.vk_index as Field, + self.vk_path, + vk_tree_root, + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/mod.nr deleted file mode 100644 index 7293961fca9d..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/mod.nr +++ /dev/null @@ -1,3 +0,0 @@ -mod verification_key; -mod proof; -mod traits; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 3b121da821ce..f48dff6111c1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -16,7 +16,6 @@ use crate::{ KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs, VMCircuitPublicInputs, }, - kernel_data::KernelData, log_hash::{EncryptedLogHash, LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, max_block_number::MaxBlockNumber, note_hash::{NoteHash, ScopedNoteHash}, @@ -40,7 +39,7 @@ use crate::{ ScopedKeyValidationRequestAndGenerator, }, }, - address::{AztecAddress, EthAddress, PublicKeysHash, SaltedInitializationHash}, + address::{AztecAddress, EthAddress, SaltedInitializationHash}, constants::{ FUNCTION_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_FIELD_VALUE, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, @@ -64,20 +63,12 @@ use crate::{ messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, partial_state_reference::PartialStateReference, point::Point, - public_keys::PublicKeys, - recursion::{ - proof::NestedRecursiveProof, + proof::{ + recursive_proof::NestedRecursiveProof, verification_key::{ClientIVCVerificationKey, HonkVerificationKey, VerificationKey}, }, - tests::fixtures::{ - self, - contract_functions::ContractFunction, - contracts::ContractData, - vk_tree::{ - generate_fake_client_ivc_vk_for_index, generate_fake_honk_vk_for_index, - get_vk_merkle_tree, VK_TREE_WIDTH, - }, - }, + public_keys::PublicKeys, + tests::fixtures::{self, contract_functions::ContractFunction, contracts::ContractData}, traits::Empty, transaction::{tx_context::TxContext, tx_request::TxRequest}, }; @@ -686,17 +677,6 @@ impl FixtureBuilder { } } - pub fn to_kernel_data(self) -> KernelData { - let public_inputs = self.to_kernel_circuit_public_inputs(); - KernelData { - public_inputs, - proof: NestedRecursiveProof::empty(), - vk: self.honk_vk, - vk_index: self.vk_index, - vk_path: self.vk_path, - } - } - pub fn add_new_note_hash(&mut self, value: Field) { self.note_hashes.push(NoteHash { value, counter: self.next_counter() }.scope( self.contract_address, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr index 5513d6d9f247..db6d9d9d9b82 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr @@ -1,15 +1,15 @@ use crate::constants::{ - BASE_PARITY_INDEX, BASE_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, + AVM_VK_INDEX, BASE_PARITY_INDEX, BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, BLOCK_ROOT_ROLLUP_INDEX, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, EMPTY_NESTED_INDEX, - HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, MERGE_ROLLUP_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, - PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_INDEX, - PRIVATE_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, PUBLIC_KERNEL_INNER_INDEX, - PUBLIC_KERNEL_MERGE_INDEX, PUBLIC_KERNEL_TAIL_INDEX, ROOT_PARITY_INDEX, ROOT_ROLLUP_INDEX, + HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, + PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, + PRIVATE_KERNEL_RESET_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, + PUBLIC_BASE_ROLLUP_VK_INDEX, ROOT_PARITY_INDEX, ROOT_ROLLUP_INDEX, TUBE_VK_INDEX, VK_TREE_HEIGHT, }; use crate::hash::verification_key_hash; use crate::merkle_tree::merkle_tree::MerkleTree; -use crate::recursion::verification_key::VerificationKey; +use crate::proof::verification_key::VerificationKey; pub global VK_TREE_WIDTH: u32 = (1 as u8 << VK_TREE_HEIGHT as u8) as u32; @@ -51,15 +51,14 @@ pub fn get_vk_merkle_tree() -> MerkleTree { leaves[EMPTY_NESTED_INDEX] = generate_fake_honk_vk_for_index(EMPTY_NESTED_INDEX).hash; leaves[PRIVATE_KERNEL_EMPTY_INDEX] = generate_fake_honk_vk_for_index(PRIVATE_KERNEL_EMPTY_INDEX).hash; - leaves[PUBLIC_KERNEL_INNER_INDEX] = - generate_fake_honk_vk_for_index(PUBLIC_KERNEL_INNER_INDEX).hash; - leaves[PUBLIC_KERNEL_MERGE_INDEX] = - generate_fake_honk_vk_for_index(PUBLIC_KERNEL_MERGE_INDEX).hash; - leaves[PUBLIC_KERNEL_TAIL_INDEX] = - generate_fake_honk_vk_for_index(PUBLIC_KERNEL_TAIL_INDEX).hash; + leaves[TUBE_VK_INDEX] = generate_fake_honk_vk_for_index(TUBE_VK_INDEX).hash; + leaves[AVM_VK_INDEX] = generate_fake_honk_vk_for_index(AVM_VK_INDEX).hash; + leaves[PRIVATE_BASE_ROLLUP_VK_INDEX] = + generate_fake_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX).hash; + leaves[PUBLIC_BASE_ROLLUP_VK_INDEX] = + generate_fake_honk_vk_for_index(PUBLIC_BASE_ROLLUP_VK_INDEX).hash; leaves[BASE_PARITY_INDEX] = generate_fake_honk_vk_for_index(BASE_PARITY_INDEX).hash; leaves[ROOT_PARITY_INDEX] = generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX).hash; - leaves[BASE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BASE_ROLLUP_INDEX).hash; leaves[MERGE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(MERGE_ROLLUP_INDEX).hash; leaves[BLOCK_ROOT_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX).hash; leaves[BLOCK_MERGE_ROLLUP_INDEX] = diff --git a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 94b096545724..7049d372153c 100644 --- a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -376,6 +376,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { fieldsWithoutPublicInputs, new Proof(binaryProof, vkData.numPublicInputs), true, + fieldsWithoutPublicInputs.length, ); return proof; } diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 52660126a9d3..490a037f64a4 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -9,10 +9,10 @@ import { import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { AGGREGATION_OBJECT_LENGTH, + AVM_PROOF_LENGTH_IN_FIELDS, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -23,13 +23,11 @@ import { type KernelCircuitPublicInputs, type MergeRollupInputs, NESTED_RECURSIVE_PROOF_LENGTH, + type PrivateBaseRollupInputs, type PrivateKernelEmptyInputData, PrivateKernelEmptyInputs, Proof, - type PublicKernelCircuitPrivateInputs, - type PublicKernelCircuitPublicInputs, - type PublicKernelInnerCircuitPrivateInputs, - type PublicKernelTailCircuitPrivateInputs, + type PublicBaseRollupInputs, RECURSIVE_PROOF_LENGTH, RecursiveProof, RootParityInput, @@ -38,13 +36,13 @@ import { type RootRollupPublicInputs, TUBE_PROOF_LENGTH, type TubeInputs, - type VMCircuitPublicInputs, type VerificationKeyAsFields, type VerificationKeyData, makeRecursiveProofFromBinary, } from '@aztec/circuits.js'; import { runInDirectory } from '@aztec/foundation/fs'; import { createDebugLogger } from '@aztec/foundation/log'; +import { BufferReader } from '@aztec/foundation/serialize'; import { Timer } from '@aztec/foundation/timer'; import { ProtocolCircuitVkIndexes, @@ -53,8 +51,6 @@ import { type ServerProtocolArtifact, convertBaseParityInputsToWitnessMap, convertBaseParityOutputsFromWitnessMap, - convertBaseRollupInputsToWitnessMap, - convertBaseRollupOutputsFromWitnessMap, convertBlockMergeRollupInputsToWitnessMap, convertBlockMergeRollupOutputsFromWitnessMap, convertBlockRootRollupInputsToWitnessMap, @@ -63,14 +59,12 @@ import { convertEmptyBlockRootRollupOutputsFromWitnessMap, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, + convertPrivateBaseRollupInputsToWitnessMap, + convertPrivateBaseRollupOutputsFromWitnessMap, convertPrivateKernelEmptyInputsToWitnessMap, convertPrivateKernelEmptyOutputsFromWitnessMap, - convertPublicInnerInputsToWitnessMap, - convertPublicInnerOutputFromWitnessMap, - convertPublicMergeInputsToWitnessMap, - convertPublicMergeOutputFromWitnessMap, - convertPublicTailInputsToWitnessMap, - convertPublicTailOutputFromWitnessMap, + convertPublicBaseRollupInputsToWitnessMap, + convertPublicBaseRollupOutputsFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -208,77 +202,35 @@ export class BBNativeRollupProver implements ServerCircuitProver { @trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({ [Attributes.APP_CIRCUIT_NAME]: inputs.functionName, })) - public async getAvmProof(inputs: AvmCircuitInputs): Promise> { + public async getAvmProof( + inputs: AvmCircuitInputs, + ): Promise>> { const proofAndVk = await this.createAvmProof(inputs); - await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey); + await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey); return proofAndVk; } /** - * Requests that a public kernel inner circuit be executed and the proof generated - * @param kernelRequest - The object encapsulating the request for a proof - * @returns The requested circuit's public inputs and proof - */ - @trackSpan('BBNativeRollupProver.getPublicKernelInnerProof', { - [Attributes.PROTOCOL_CIRCUIT_NAME]: 'public-kernel-inner', - }) - public async getPublicKernelInnerProof( - inputs: PublicKernelInnerCircuitPrivateInputs, - ): Promise> { - const artifact = 'PublicKernelInnerArtifact'; - - const { circuitOutput, proof } = await this.createRecursiveProof( - inputs, - artifact, - NESTED_RECURSIVE_PROOF_LENGTH, - convertPublicInnerInputsToWitnessMap, - convertPublicInnerOutputFromWitnessMap, - ); - - const verificationKey = await this.getVerificationKeyDataForCircuit(artifact); - - await this.verifyProof(artifact, proof.binaryProof); - - return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); - } - - /** - * Requests that a public kernel merge circuit be executed and the proof generated - * @param kernelRequest - The object encapsulating the request for a proof - * @returns The requested circuit's public inputs and proof + * Simulates the base rollup circuit from its inputs. + * @param inputs - Inputs to the circuit. + * @returns The public inputs as outputs of the simulation. */ - @trackSpan('BBNativeRollupProver.getPublicKernelMergeProof', { - [Attributes.PROTOCOL_CIRCUIT_NAME]: 'public-kernel-merge', - }) - public async getPublicKernelMergeProof( - inputs: PublicKernelCircuitPrivateInputs, - ): Promise> { - const artifact = 'PublicKernelMergeArtifact'; - - // We may need to convert the recursive proof into fields format - inputs.previousKernel.proof = await this.ensureValidProof( - inputs.previousKernel.proof, - artifact, - inputs.previousKernel.vk, - ); - - await this.verifyWithKey( - getUltraHonkFlavorForCircuit(artifact), - inputs.previousKernel.vk, - inputs.previousKernel.proof.binaryProof, - ); + public async getPrivateBaseRollupProof( + inputs: PrivateBaseRollupInputs, + ): Promise> { + const artifactName = 'PrivateBaseRollupArtifact'; const { circuitOutput, proof } = await this.createRecursiveProof( inputs, - artifact, + artifactName, NESTED_RECURSIVE_PROOF_LENGTH, - convertPublicMergeInputsToWitnessMap, - convertPublicMergeOutputFromWitnessMap, + convertPrivateBaseRollupInputsToWitnessMap, + convertPrivateBaseRollupOutputsFromWitnessMap, ); - const verificationKey = await this.getVerificationKeyDataForCircuit(artifact); + const verificationKey = await this.getVerificationKeyDataForCircuit(artifactName); - await this.verifyProof(artifact, proof.binaryProof); + await this.verifyProof(artifactName, proof.binaryProof); return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); } @@ -288,52 +240,22 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @param kernelRequest - The object encapsulating the request for a proof * @returns The requested circuit's public inputs and proof */ - public async getPublicTailProof( - inputs: PublicKernelTailCircuitPrivateInputs, - ): Promise> { - const { circuitOutput, proof } = await this.createRecursiveProof( - inputs, - 'PublicKernelTailArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, - convertPublicTailInputsToWitnessMap, - convertPublicTailOutputFromWitnessMap, - ); - - const verificationKey = await this.getVerificationKeyDataForCircuit('PublicKernelTailArtifact'); - - await this.verifyProof('PublicKernelTailArtifact', proof.binaryProof); - - return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); - } - - /** - * Simulates the base rollup circuit from its inputs. - * @param baseRollupInput - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async getBaseRollupProof( - baseRollupInput: BaseRollupInputs, // TODO: remove tail proof from here + public async getPublicBaseRollupProof( + inputs: PublicBaseRollupInputs, ): Promise> { - // We may need to convert the recursive proof into fields format - logger.debug(`kernel Data proof: ${baseRollupInput.kernelData.proof}`); - logger.debug(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`); - baseRollupInput.kernelData.proof = await this.ensureValidProof( - baseRollupInput.kernelData.proof, - 'BaseRollupArtifact', - baseRollupInput.kernelData.vk, - ); + const artifactName = 'PublicBaseRollupArtifact'; const { circuitOutput, proof } = await this.createRecursiveProof( - baseRollupInput, // BaseRollupInputs - 'BaseRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, // WORKTODO: this should be BASE_ROLLUP_PROOF_LENGTH or something like this - convertBaseRollupInputsToWitnessMap, - convertBaseRollupOutputsFromWitnessMap, + inputs, + artifactName, + NESTED_RECURSIVE_PROOF_LENGTH, + convertPublicBaseRollupInputsToWitnessMap, + convertPublicBaseRollupOutputsFromWitnessMap, ); - const verificationKey = await this.getVerificationKeyDataForCircuit('BaseRollupArtifact'); + const verificationKey = await this.getVerificationKeyDataForCircuit(artifactName); - await this.verifyProof('BaseRollupArtifact', proof.binaryProof); + await this.verifyProof(artifactName, proof.binaryProof); return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); } @@ -677,20 +599,21 @@ export class BBNativeRollupProver implements ServerCircuitProver { return provingResult; } - private async createAvmProof(input: AvmCircuitInputs): Promise> { - const operation = async (bbWorkingDirectory: string): Promise> => { + private async createAvmProof( + input: AvmCircuitInputs, + ): Promise>> { + const operation = async (bbWorkingDirectory: string) => { const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory); - const rawProof = await fs.readFile(provingResult.proofPath!); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong. // In particular, the number of public inputs, etc will be wrong. const verificationKey = await extractAvmVkData(provingResult.vkPath!); - const proof = new Proof(rawProof, verificationKey.numPublicInputs); + const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!, verificationKey); const circuitType = 'avm-circuit' as const; const appCircuitName = 'unknown' as const; this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs); - this.instrumentation.recordAvmSize('proofSize', appCircuitName, proof.buffer.length); + this.instrumentation.recordAvmSize('proofSize', appCircuitName, avmProof.binaryProof.buffer.length); this.instrumentation.recordAvmSize('circuitPublicInputCount', appCircuitName, verificationKey.numPublicInputs); this.instrumentation.recordAvmSize('circuitSize', appCircuitName, verificationKey.circuitSize); @@ -701,7 +624,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { appCircuitName: input.functionName, // does not include reading the proof from disk duration: provingResult.durationMs, - proofSize: proof.buffer.length, + proofSize: avmProof.binaryProof.buffer.length, eventName: 'circuit-proving', inputSize: input.toBuffer().length, circuitSize: verificationKey.circuitSize, // FIX: wrong in VK @@ -709,7 +632,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { } satisfies CircuitProvingStats, ); - return makeProofAndVerificationKey(proof, verificationKey); + return makeProofAndVerificationKey(avmProof, verificationKey); }; return await this.runInDirectory(operation); } @@ -724,7 +647,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { // Read the proof as fields const tubeVK = await extractVkData(provingResult.vkPath!); - const tubeProof = await this.readTubeProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH); + const tubeProof = await this.readProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH); this.instrumentation.recordDuration('provingDuration', 'tubeCircuit', provingResult.durationMs); this.instrumentation.recordSize('proofSize', 'tubeCircuit', tubeProof.binaryProof.buffer.length); @@ -774,7 +697,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { } = await this.generateProofWithBB(input, circuitType, convertInput, convertOutput, bbWorkingDirectory); // Read the proof as fields - const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength); + const proof = await this.readProofAsFields(provingResult.proofPath!, vkData, proofLength); const circuitName = mapProtocolArtifactNameToCircuitName(circuitType); this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs); @@ -914,10 +837,11 @@ export class BBNativeRollupProver implements ServerCircuitProver { .slice(0, 3) .map(Fr.fromString) .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); - return new RecursiveProof( + return new RecursiveProof( fields, new Proof(proof.binaryProof.buffer, vk.numPublicInputs), true, + NESTED_RECURSIVE_PROOF_LENGTH, ); }; return await this.runInDirectory(operation); @@ -969,15 +893,9 @@ export class BBNativeRollupProver implements ServerCircuitProver { return promise; } - /** - * Parses and returns the proof data stored at the specified directory - * @param filePath - The directory containing the proof data - * @param circuitType - The type of circuit proven - * @returns The proof - */ private async readProofAsFields( filePath: string, - circuitType: ServerProtocolArtifact, + vkData: VerificationKeyData, proofLength: PROOF_LENGTH, ): Promise> { const proofFilename = path.join(filePath, PROOF_FILENAME); @@ -987,67 +905,35 @@ export class BBNativeRollupProver implements ServerCircuitProver { fs.readFile(proofFilename), fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }), ]); + const json = JSON.parse(proofString); - const vkData = await this.getVerificationKeyDataForCircuit(circuitType); + const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const fieldsWithoutPublicInputs = json .slice(0, 3) .map(Fr.fromString) .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); - logger.debug(`num pub inputs ${vkData.numPublicInputs} circuit=${circuitType}`); - - const proof = new RecursiveProof( - fieldsWithoutPublicInputs, - new Proof(binaryProof, numPublicInputs), - true, + logger.debug( + `Circuit path: ${filePath}, complete proof length: ${json.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, ); - if (proof.proof.length !== proofLength) { - throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`); - } - return proof; + return new RecursiveProof(fieldsWithoutPublicInputs, new Proof(binaryProof, numPublicInputs), true, proofLength); } - /** - * Parses and returns a tube proof stored in the specified directory. TODO merge wih above - * @param filePath - The directory containing the proof data - * @param circuitType - The type of circuit proven - * @returns The proof - * TODO(#7369) This is entirely redundant now with the above method, deduplicate - */ - private async readTubeProofAsFields( - filePath: string, + private async readAvmProofAsFields( + proofFilename: string, vkData: VerificationKeyData, - proofLength: PROOF_LENGTH, - ): Promise> { - const proofFilename = path.join(filePath, PROOF_FILENAME); - const proofFieldsFilename = path.join(filePath, PROOF_FIELDS_FILENAME); - - const [binaryProof, proofString] = await Promise.all([ - fs.readFile(proofFilename), - fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }), - ]); + ): Promise> { + const rawProof = await fs.readFile(proofFilename); - const json = JSON.parse(proofString); + const reader = BufferReader.asReader(rawProof); + const fields = reader.readArray(rawProof.length / Fr.SIZE_IN_BYTES, Fr); + const fieldsWithoutPublicCols = fields.slice(-1 * AVM_PROOF_LENGTH_IN_FIELDS); - const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; - if (numPublicInputs === 0) { - throw new Error(`Tube proof should have public inputs (e.g. the number of public inputs from PrivateKernelTail)`); - } - - const proofFields = json - .slice(0, 3) - .map(Fr.fromString) - .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); - logger.debug( - `Circuit type: tube circuit, complete proof length: ${json.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, - ); - const proof = new RecursiveProof(proofFields, new Proof(binaryProof, numPublicInputs), true); - if (proof.proof.length !== proofLength) { - throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`); - } + const proof = new Proof(rawProof, vkData.numPublicInputs); - return proof; + return new RecursiveProof(fieldsWithoutPublicCols, proof, true, AVM_PROOF_LENGTH_IN_FIELDS); } private runInDirectory(fn: (dir: string) => Promise) { diff --git a/yarn-project/bb-prover/src/stats.ts b/yarn-project/bb-prover/src/stats.ts index c5dc96bd38cb..b517acdb1ca2 100644 --- a/yarn-project/bb-prover/src/stats.ts +++ b/yarn-project/bb-prover/src/stats.ts @@ -9,8 +9,10 @@ export function mapProtocolArtifactNameToCircuitName( return 'base-parity'; case 'RootParityArtifact': return 'root-parity'; - case 'BaseRollupArtifact': - return 'base-rollup'; + case 'PrivateBaseRollupArtifact': + return 'private-base-rollup'; + case 'PublicBaseRollupArtifact': + return 'public-base-rollup'; case 'MergeRollupArtifact': return 'merge-rollup'; case 'BlockRootRollupArtifact': @@ -21,12 +23,6 @@ export function mapProtocolArtifactNameToCircuitName( return 'block-merge-rollup'; case 'RootRollupArtifact': return 'root-rollup'; - case 'PublicKernelInnerArtifact': - return 'public-kernel-inner'; - case 'PublicKernelMergeArtifact': - return 'public-kernel-merge'; - case 'PublicKernelTailArtifact': - return 'public-kernel-tail'; case 'PrivateKernelInitArtifact': return 'private-kernel-init'; case 'PrivateKernelInnerArtifact': diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index 89a5ebf4d426..6deb323b5023 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -6,11 +6,11 @@ import { makePublicInputsAndRecursiveProof, } from '@aztec/circuit-types'; import { + AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -19,13 +19,11 @@ import { type KernelCircuitPublicInputs, type MergeRollupInputs, NESTED_RECURSIVE_PROOF_LENGTH, + type PrivateBaseRollupInputs, type PrivateKernelEmptyInputData, PrivateKernelEmptyInputs, type Proof, - type PublicKernelCircuitPrivateInputs, - type PublicKernelCircuitPublicInputs, - type PublicKernelInnerCircuitPrivateInputs, - type PublicKernelTailCircuitPrivateInputs, + type PublicBaseRollupInputs, RECURSIVE_PROOF_LENGTH, type RecursiveProof, RootParityInput, @@ -34,9 +32,7 @@ import { type RootRollupPublicInputs, TUBE_PROOF_LENGTH, type TubeInputs, - type VMCircuitPublicInputs, VerificationKeyData, - makeEmptyProof, makeEmptyRecursiveProof, makeRecursiveProof, } from '@aztec/circuits.js'; @@ -64,20 +60,18 @@ import { convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, convertRootRollupOutputsFromWitnessMap, - convertSimulatedBaseRollupInputsToWitnessMap, - convertSimulatedBaseRollupOutputsFromWitnessMap, + convertSimulatedPrivateBaseRollupInputsToWitnessMap, + convertSimulatedPrivateBaseRollupOutputsFromWitnessMap, convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap, - convertSimulatedPublicInnerInputsToWitnessMap, - convertSimulatedPublicInnerOutputFromWitnessMap, - convertSimulatedPublicMergeInputsToWitnessMap, - convertSimulatedPublicMergeOutputFromWitnessMap, - convertSimulatedPublicTailInputsToWitnessMap, - convertSimulatedPublicTailOutputFromWitnessMap, + convertSimulatedPublicBaseRollupInputsToWitnessMap, + convertSimulatedPublicBaseRollupOutputsFromWitnessMap, getVKSiblingPath, } from '@aztec/noir-protocol-circuits-types'; import { type SimulationProvider, WASMSimulator, emitCircuitSimulationStats } from '@aztec/simulator'; import { type TelemetryClient, trackSpan } from '@aztec/telemetry-client'; +import { type WitnessMap } from '@noir-lang/types'; + import { ProverInstrumentation } from '../instrumentation.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; @@ -117,17 +111,13 @@ export class TestCircuitProver implements ServerCircuitProver { inputs.vkTreeRoot, inputs.protocolContractTreeRoot, ); - const witnessMap = convertPrivateKernelEmptyInputsToWitnessMap(kernelInputs); - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact, - ); - const result = convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap(witness); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['PrivateKernelEmptyArtifact'], + + return await this.simulate( + kernelInputs, + 'PrivateKernelEmptyArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertPrivateKernelEmptyInputsToWitnessMap, + convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap, ); } @@ -146,17 +136,13 @@ export class TestCircuitProver implements ServerCircuitProver { inputs.vkTreeRoot, inputs.protocolContractTreeRoot, ); - const witnessMap = convertPrivateKernelEmptyInputsToWitnessMap(kernelInputs); - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact, - ); - const result = convertPrivateKernelEmptyOutputsFromWitnessMap(witness); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + + return await this.simulate( + kernelInputs, + 'EmptyNestedArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertPrivateKernelEmptyInputsToWitnessMap, + convertPrivateKernelEmptyOutputsFromWitnessMap, ); } @@ -167,34 +153,20 @@ export class TestCircuitProver implements ServerCircuitProver { */ @trackSpan('TestCircuitProver.getBaseParityProof') public async getBaseParityProof(inputs: BaseParityInputs): Promise> { - const timer = new Timer(); - const witnessMap = convertBaseParityInputsToWitnessMap(inputs); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BaseParityArtifact, + const result = await this.simulate( + inputs, + 'BaseParityArtifact', + RECURSIVE_PROOF_LENGTH, + convertBaseParityInputsToWitnessMap, + convertBaseParityOutputsFromWitnessMap, ); - const result = convertBaseParityOutputsFromWitnessMap(witness); - const rootParityInput = new RootParityInput( - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['BaseParityArtifact'].keyAsFields, + return new RootParityInput( + result.proof, + result.verificationKey.keyAsFields, getVKSiblingPath(ProtocolCircuitVkIndexes['BaseParityArtifact']), - result, - ); - - this.instrumentation.recordDuration('simulationDuration', 'base-parity', timer); - - emitCircuitSimulationStats( - 'base-parity', - timer.ms(), - inputs.toBuffer().length, - result.toBuffer().length, - this.logger, + result.inputs, ); - await this.delay(); - return Promise.resolve(rootParityInput); } /** @@ -206,77 +178,53 @@ export class TestCircuitProver implements ServerCircuitProver { public async getRootParityProof( inputs: RootParityInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertRootParityInputsToWitnessMap(inputs); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.RootParityArtifact, + const result = await this.simulate( + inputs, + 'RootParityArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertRootParityInputsToWitnessMap, + convertRootParityOutputsFromWitnessMap, ); - const result = convertRootParityOutputsFromWitnessMap(witness); - - const rootParityInput = new RootParityInput( - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['RootParityArtifact'].keyAsFields, + return new RootParityInput( + result.proof, + result.verificationKey.keyAsFields, getVKSiblingPath(ProtocolCircuitVkIndexes['RootParityArtifact']), - result, + result.inputs, ); + } - this.instrumentation.recordDuration('simulationDuration', 'root-parity', timer); - emitCircuitSimulationStats( - 'root-parity', - timer.ms(), - inputs.toBuffer().length, - result.toBuffer().length, - this.logger, - ); + public async getTubeProof( + _tubeInput: TubeInputs, + ): Promise>> { await this.delay(); - return Promise.resolve(rootParityInput); + return makeProofAndVerificationKey(makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()); } - /** - * Simulates the base rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - @trackSpan('TestCircuitProver.getBaseRollupProof') - public async getBaseRollupProof( - input: BaseRollupInputs, + @trackSpan('TestCircuitProver.getPrivateBaseRollupProof') + public async getPrivateBaseRollupProof( + inputs: PrivateBaseRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertSimulatedBaseRollupInputsToWitnessMap(input); - - const simulationProvider = this.simulationProvider ?? this.wasmSimulator; - const witness = await simulationProvider.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BaseRollupArtifact, - ); - - const result = convertSimulatedBaseRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'base-rollup', timer); - emitCircuitSimulationStats( - 'base-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['BaseRollupArtifact'], + return await this.simulate( + inputs, + 'PrivateBaseRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertSimulatedPrivateBaseRollupInputsToWitnessMap, + convertSimulatedPrivateBaseRollupOutputsFromWitnessMap, ); } - public async getTubeProof( - _tubeInput: TubeInputs, - ): Promise>> { - await this.delay(); - return makeProofAndVerificationKey(makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()); + @trackSpan('TestCircuitProver.getPublicBaseRollupProof') + public async getPublicBaseRollupProof( + inputs: PublicBaseRollupInputs, + ): Promise> { + return await this.simulate( + inputs, + 'PublicBaseRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertSimulatedPublicBaseRollupInputsToWitnessMap, + convertSimulatedPublicBaseRollupOutputsFromWitnessMap, + ); } /** @@ -288,30 +236,12 @@ export class TestCircuitProver implements ServerCircuitProver { public async getMergeRollupProof( input: MergeRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertMergeRollupInputsToWitnessMap(input); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.MergeRollupArtifact, - ); - - const result = convertMergeRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'merge-rollup', timer); - emitCircuitSimulationStats( - 'merge-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['MergeRollupArtifact'], + return await this.simulate( + input, + 'MergeRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertMergeRollupInputsToWitnessMap, + convertMergeRollupOutputsFromWitnessMap, ); } @@ -324,29 +254,12 @@ export class TestCircuitProver implements ServerCircuitProver { public async getBlockRootRollupProof( input: BlockRootRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertBlockRootRollupInputsToWitnessMap(input); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BlockRootRollupArtifact, - ); - - const result = convertBlockRootRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'block-root-rollup', timer); - emitCircuitSimulationStats( - 'block-root-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['BlockRootRollupArtifact'], + return await this.simulate( + input, + 'BlockRootRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertBlockRootRollupInputsToWitnessMap, + convertBlockRootRollupOutputsFromWitnessMap, ); } @@ -359,29 +272,12 @@ export class TestCircuitProver implements ServerCircuitProver { public async getEmptyBlockRootRollupProof( input: EmptyBlockRootRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertEmptyBlockRootRollupInputsToWitnessMap(input); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.EmptyBlockRootRollupArtifact, - ); - - const result = convertEmptyBlockRootRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'empty-block-root-rollup', timer); - emitCircuitSimulationStats( - 'empty-block-root-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['EmptyBlockRootRollupArtifact'], + return await this.simulate( + input, + 'EmptyBlockRootRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertEmptyBlockRootRollupInputsToWitnessMap, + convertEmptyBlockRootRollupOutputsFromWitnessMap, ); } @@ -394,29 +290,12 @@ export class TestCircuitProver implements ServerCircuitProver { public async getBlockMergeRollupProof( input: BlockMergeRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertBlockMergeRollupInputsToWitnessMap(input); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BlockMergeRollupArtifact, - ); - - const result = convertBlockMergeRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'block-merge-rollup', timer); - emitCircuitSimulationStats( - 'block-merge-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['BlockMergeRollupArtifact'], + return await this.simulate( + input, + 'BlockMergeRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertBlockMergeRollupInputsToWitnessMap, + convertBlockMergeRollupOutputsFromWitnessMap, ); } @@ -429,128 +308,24 @@ export class TestCircuitProver implements ServerCircuitProver { public async getRootRollupProof( input: RootRollupInputs, ): Promise> { - const timer = new Timer(); - const witnessMap = convertRootRollupInputsToWitnessMap(input); - - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.RootRollupArtifact, - ); - - const result = convertRootRollupOutputsFromWitnessMap(witness); - - this.instrumentation.recordDuration('simulationDuration', 'root-rollup', timer); - emitCircuitSimulationStats( - 'root-rollup', - timer.ms(), - input.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['RootRollupArtifact'], - ); - } - - @trackSpan('TestCircuitProver.getPublicKernelInnerProof') - public async getPublicKernelInnerProof( - inputs: PublicKernelInnerCircuitPrivateInputs, - ): Promise> { - const timer = new Timer(); - - const artifact = 'PublicKernelInnerArtifact'; - const circuitName = mapProtocolArtifactNameToCircuitName(artifact); - - const witnessMap = convertSimulatedPublicInnerInputsToWitnessMap(inputs); - const witness = await this.wasmSimulator.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifact]); - - const result = convertSimulatedPublicInnerOutputFromWitnessMap(witness); - this.instrumentation.recordDuration('simulationDuration', circuitName, timer); - emitCircuitSimulationStats( - circuitName, - timer.ms(), - inputs.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks[artifact], + return await this.simulate( + input, + 'RootRollupArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertRootRollupInputsToWitnessMap, + convertRootRollupOutputsFromWitnessMap, ); } - @trackSpan('TestCircuitProver.getPublicKernelMergeProof') - public async getPublicKernelMergeProof( - inputs: PublicKernelCircuitPrivateInputs, - ): Promise> { - const timer = new Timer(); - - const artifact = 'PublicKernelMergeArtifact'; - const circuitName = mapProtocolArtifactNameToCircuitName(artifact); - - const witnessMap = convertSimulatedPublicMergeInputsToWitnessMap(inputs); - const witness = await this.wasmSimulator.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifact]); - - const result = convertSimulatedPublicMergeOutputFromWitnessMap(witness); - this.instrumentation.recordDuration('simulationDuration', circuitName, timer); - emitCircuitSimulationStats( - circuitName, - timer.ms(), - inputs.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks[artifact], - ); - } - - @trackSpan('TestCircuitProver.getPublicTailProof') - public async getPublicTailProof( - inputs: PublicKernelTailCircuitPrivateInputs, - ): Promise> { - const timer = new Timer(); - - const artifact = 'PublicKernelTailArtifact'; - const circuitName = mapProtocolArtifactNameToCircuitName(artifact); - - const witnessMap = convertSimulatedPublicTailInputsToWitnessMap(inputs); - // use WASM here as it is faster for small circuits - const witness = await this.wasmSimulator.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifact]); - - const result = convertSimulatedPublicTailOutputFromWitnessMap(witness); - this.instrumentation.recordDuration('simulationDuration', circuitName, timer); - emitCircuitSimulationStats( - circuitName, - timer.ms(), - inputs.toBuffer().length, - result.toBuffer().length, - this.logger, - ); - await this.delay(); - return makePublicInputsAndRecursiveProof( - result, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks[artifact], - ); - } - - public async getAvmProof(_inputs: AvmCircuitInputs): Promise> { + public async getAvmProof( + _inputs: AvmCircuitInputs, + ): Promise>> { // We can't simulate the AVM because we don't have enough context to do so (e.g., DBs). // We just return an empty proof and VK data. this.logger.debug('Skipping AVM simulation in TestCircuitProver.'); await this.delay(); return makeProofAndVerificationKey( - makeEmptyProof(), + makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS), ); } @@ -565,4 +340,30 @@ export class TestCircuitProver implements ServerCircuitProver { public verifyProof(_1: ServerProtocolArtifact, _2: Proof): Promise { return Promise.reject(new Error('Method not implemented.')); } + + private async simulate< + PROOF_LENGTH extends number, + CircuitInputType extends { toBuffer: () => Buffer }, + CircuitOutputType extends { toBuffer: () => Buffer }, + >( + input: CircuitInputType, + artifactName: ServerProtocolArtifact, + proofLength: PROOF_LENGTH, + convertInput: (input: CircuitInputType) => WitnessMap, + convertOutput: (outputWitness: WitnessMap) => CircuitOutputType, + ) { + const timer = new Timer(); + const witnessMap = convertInput(input); + const circuitName = mapProtocolArtifactNameToCircuitName(artifactName); + + const simulationProvider = this.simulationProvider ?? this.wasmSimulator; + const witness = await simulationProvider.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifactName]); + + const result = convertOutput(witness); + + this.instrumentation.recordDuration('simulationDuration', circuitName, timer); + emitCircuitSimulationStats(circuitName, timer.ms(), input.toBuffer().length, result.toBuffer().length, this.logger); + await this.delay(); + return makePublicInputsAndRecursiveProof(result, makeRecursiveProof(proofLength), ProtocolCircuitVks[artifactName]); + } } diff --git a/yarn-project/circuit-types/src/interfaces/proving-job.ts b/yarn-project/circuit-types/src/interfaces/proving-job.ts index 49e504ab49df..1814c6a107b2 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job.ts @@ -1,8 +1,8 @@ import { + type AVM_PROOF_LENGTH_IN_FIELDS, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -10,12 +10,9 @@ import { type KernelCircuitPublicInputs, type MergeRollupInputs, type NESTED_RECURSIVE_PROOF_LENGTH, + type PrivateBaseRollupInputs, type PrivateKernelEmptyInputData, - type Proof, - type PublicKernelCircuitPrivateInputs, - type PublicKernelCircuitPublicInputs, - type PublicKernelInnerCircuitPrivateInputs, - type PublicKernelTailCircuitPrivateInputs, + type PublicBaseRollupInputs, type RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootParityInput, @@ -24,7 +21,6 @@ import { type RootRollupPublicInputs, type TUBE_PROOF_LENGTH, type TubeInputs, - type VMCircuitPublicInputs, type VerificationKeyData, } from '@aztec/circuits.js'; @@ -70,11 +66,8 @@ export enum ProvingRequestType { PRIVATE_KERNEL_EMPTY, PUBLIC_VM, - PUBLIC_KERNEL_INNER, - PUBLIC_KERNEL_MERGE, - PUBLIC_KERNEL_TAIL, - - BASE_ROLLUP, + PRIVATE_BASE_ROLLUP, + PUBLIC_BASE_ROLLUP, MERGE_ROLLUP, EMPTY_BLOCK_ROOT_ROLLUP, BLOCK_ROOT_ROLLUP, @@ -93,14 +86,10 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Ci return 'private-kernel-empty'; case ProvingRequestType.PUBLIC_VM: return 'avm-circuit'; - case ProvingRequestType.PUBLIC_KERNEL_INNER: - return 'public-kernel-inner'; - case ProvingRequestType.PUBLIC_KERNEL_MERGE: - return 'public-kernel-merge'; - case ProvingRequestType.PUBLIC_KERNEL_TAIL: - return 'public-kernel-tail'; - case ProvingRequestType.BASE_ROLLUP: - return 'base-rollup'; + case ProvingRequestType.PRIVATE_BASE_ROLLUP: + return 'private-base-rollup'; + case ProvingRequestType.PUBLIC_BASE_ROLLUP: + return 'public-base-rollup'; case ProvingRequestType.MERGE_ROLLUP: return 'merge-rollup'; case ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP: @@ -122,29 +111,13 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Ci } } -export type PublicKernelInnerRequest = { - type: ProvingRequestType.PUBLIC_KERNEL_INNER; - inputs: PublicKernelInnerCircuitPrivateInputs; -}; - -export type PublicKernelMergeRequest = { - type: ProvingRequestType.PUBLIC_KERNEL_MERGE; - inputs: PublicKernelCircuitPrivateInputs; -}; - -export type PublicKernelTailRequest = { - type: ProvingRequestType.PUBLIC_KERNEL_TAIL; - inputs: PublicKernelTailCircuitPrivateInputs; +export type AvmProvingRequest = { + type: ProvingRequestType.PUBLIC_VM; + inputs: AvmCircuitInputs; }; export type ProvingRequest = - | { - type: ProvingRequestType.PUBLIC_VM; - inputs: AvmCircuitInputs; - } - | PublicKernelInnerRequest - | PublicKernelMergeRequest - | PublicKernelTailRequest + | AvmProvingRequest | { type: ProvingRequestType.BASE_PARITY; inputs: BaseParityInputs; @@ -154,8 +127,12 @@ export type ProvingRequest = inputs: RootParityInputs; } | { - type: ProvingRequestType.BASE_ROLLUP; - inputs: BaseRollupInputs; + type: ProvingRequestType.PRIVATE_BASE_ROLLUP; + inputs: PrivateBaseRollupInputs; + } + | { + type: ProvingRequestType.PUBLIC_BASE_ROLLUP; + inputs: PublicBaseRollupInputs; } | { type: ProvingRequestType.MERGE_ROLLUP; @@ -186,27 +163,22 @@ export type ProvingRequest = inputs: TubeInputs; }; -export type ProvingRequestPublicInputs = { +export type ProvingRequestResults = { [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: PublicInputsAndRecursiveProof; - [ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey; - - [ProvingRequestType.PUBLIC_KERNEL_INNER]: PublicInputsAndRecursiveProof; - [ProvingRequestType.PUBLIC_KERNEL_MERGE]: PublicInputsAndRecursiveProof; - [ProvingRequestType.PUBLIC_KERNEL_TAIL]: PublicInputsAndRecursiveProof; - - [ProvingRequestType.BASE_ROLLUP]: PublicInputsAndRecursiveProof; + [ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey>; + [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PublicInputsAndRecursiveProof; + [ProvingRequestType.PUBLIC_BASE_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.MERGE_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.BLOCK_MERGE_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.ROOT_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.BASE_PARITY]: RootParityInput; [ProvingRequestType.ROOT_PARITY]: RootParityInput; [ProvingRequestType.TUBE_PROOF]: ProofAndVerificationKey>; }; -export type ProvingRequestResult = ProvingRequestPublicInputs[T]; +export type ProvingRequestResult = ProvingRequestResults[T]; export interface ProvingJobSource { /** diff --git a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts index 8339596657fb..fd3578a10326 100644 --- a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts @@ -1,8 +1,8 @@ import { + type AVM_PROOF_LENGTH_IN_FIELDS, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -10,12 +10,9 @@ import { type KernelCircuitPublicInputs, type MergeRollupInputs, type NESTED_RECURSIVE_PROOF_LENGTH, + type PrivateBaseRollupInputs, type PrivateKernelEmptyInputData, - type Proof, - type PublicKernelCircuitPrivateInputs, - type PublicKernelCircuitPublicInputs, - type PublicKernelInnerCircuitPrivateInputs, - type PublicKernelTailCircuitPrivateInputs, + type PublicBaseRollupInputs, type RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootParityInput, @@ -24,7 +21,6 @@ import { type RootRollupPublicInputs, type TUBE_PROOF_LENGTH, type TubeInputs, - type VMCircuitPublicInputs, } from '@aztec/circuits.js'; import type { Tx } from '../tx/tx.js'; @@ -58,8 +54,14 @@ export interface ServerCircuitProver { * Creates a proof for the given input. * @param input - Input to the circuit. */ - getBaseRollupProof( - baseRollupInput: BaseRollupInputs, + getPrivateBaseRollupProof( + baseRollupInput: PrivateBaseRollupInputs, + signal?: AbortSignal, + epochNumber?: number, + ): Promise>; + + getPublicBaseRollupProof( + inputs: PublicBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, ): Promise>; @@ -124,28 +126,6 @@ export interface ServerCircuitProver { epochNumber?: number, ): Promise>; - /** - * Create a public kernel inner proof. - * @param kernelRequest - Object containing the details of the proof required - */ - getPublicKernelInnerProof( - inputs: PublicKernelInnerCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise>; - - getPublicKernelMergeProof( - inputs: PublicKernelCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise>; - - getPublicTailProof( - inputs: PublicKernelTailCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise>; - getEmptyPrivateKernelProof( inputs: PrivateKernelEmptyInputData, signal?: AbortSignal, @@ -166,7 +146,7 @@ export interface ServerCircuitProver { inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise>>; } /** diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index c47c35154a52..c75d84bf2e43 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -76,7 +76,8 @@ export type NodeSyncedChainHistoryStats = { export type CircuitName = | 'base-parity' | 'root-parity' - | 'base-rollup' + | 'private-base-rollup' + | 'public-base-rollup' | 'merge-rollup' | 'block-root-rollup' | 'empty-block-root-rollup' @@ -88,9 +89,6 @@ export type CircuitName = | 'private-kernel-tail' | 'private-kernel-tail-to-public' | 'app-circuit' - | 'public-kernel-inner' - | 'public-kernel-merge' - | 'public-kernel-tail' | 'avm-circuit' | 'empty-nested' | 'private-kernel-empty' diff --git a/yarn-project/circuit-types/src/test/factories.ts b/yarn-project/circuit-types/src/test/factories.ts index f93b26ffb187..b0d5e8f71c86 100644 --- a/yarn-project/circuit-types/src/test/factories.ts +++ b/yarn-project/circuit-types/src/test/factories.ts @@ -43,7 +43,7 @@ export function makeBloatedProcessedTx( kernelOutput.constants.txContext.gasSettings = GasSettings.default({ inclusionFee: overrides.inclusionFee }); - const processedTx = makeProcessedTx(tx, kernelOutput, []); + const processedTx = makeProcessedTx(tx, kernelOutput); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => new Fr(i), seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, i => new Fr(i), seed + 0x100000); diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index 5ed05d29d135..63345772338f 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -1,11 +1,9 @@ import { + type AvmProvingRequest, EncryptedNoteTxL2Logs, EncryptedTxL2Logs, PublicDataWrite, type PublicInputsAndRecursiveProof, - type PublicKernelInnerRequest, - type PublicKernelMergeRequest, - type PublicKernelTailRequest, type SimulationError, type Tx, TxEffect, @@ -13,7 +11,6 @@ import { UnencryptedTxL2Logs, } from '@aztec/circuit-types'; import { - type AvmExecutionHints, ClientIvcProof, Fr, type Gas, @@ -35,21 +32,6 @@ export enum PublicKernelPhase { TEARDOWN, } -export type PublicKernelRequest = PublicKernelInnerRequest | PublicKernelMergeRequest | PublicKernelTailRequest; - -export const AVM_REQUEST = 'AVM' as const; - -export type AvmProvingRequest = { - type: typeof AVM_REQUEST; - functionName: string; // informational only - bytecode: Buffer; - calldata: Fr[]; - avmHints: AvmExecutionHints; - kernelRequest: PublicKernelInnerRequest; -}; - -export type PublicProvingRequest = AvmProvingRequest | PublicKernelRequest; - /** * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. @@ -72,9 +54,9 @@ export type ProcessedTx = Pick { - if (CPP_CONSTANTS.includes(key) || key.startsWith('AVM_')) { + if (CPP_CONSTANTS.includes(key) || (key.startsWith('AVM_') && key !== 'AVM_VK_INDEX')) { // stringify large numbers code.push(`#define ${key} ${BigInt(value) > 2n ** 31n - 1n ? `"0x${BigInt(value).toString(16)}"` : value}`); } diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 611652fe46e9..022fa88bc440 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -18,7 +18,6 @@ export * from './kernel/combined_constant_data.js'; export * from './kernel/enqueued_call_data.js'; export * from './kernel/private_kernel_empty_inputs.js'; export * from './kernel/kernel_circuit_public_inputs.js'; -export * from './kernel/kernel_data.js'; export * from './kernel/private_accumulated_data.js'; export * from './kernel/private_call_data.js'; export * from './kernel/private_kernel_circuit_public_inputs.js'; @@ -73,17 +72,24 @@ export * from './read_request_hints/index.js'; export * from './recursive_proof.js'; export * from './revert_code.js'; export * from './rollup/append_only_tree_snapshot.js'; +export * from './rollup/avm_proof_data.js'; export * from './rollup/base_or_merge_rollup_public_inputs.js'; -export * from './rollup/base_rollup.js'; +export * from './rollup/base_rollup_hints.js'; export * from './rollup/block_merge_rollup.js'; export * from './rollup/block_root_or_block_merge_public_inputs.js'; +export * from './rollup/constant_rollup_data.js'; export * from './rollup/empty_block_root_rollup_inputs.js'; export * from './rollup/block_root_rollup.js'; export * from './rollup/merge_rollup.js'; export * from './rollup/previous_rollup_block_data.js'; export * from './rollup/previous_rollup_data.js'; +export * from './rollup/private_base_rollup_inputs.js'; +export * from './rollup/private_tube_data.js'; +export * from './rollup/public_base_rollup_inputs.js'; +export * from './rollup/public_tube_data.js'; export * from './rollup/root_rollup.js'; export * from './rollup/state_diff_hints.js'; +export * from './rollup/tube_inputs.js'; export * from './rollup_validation_requests.js'; export * from './scoped_key_validation_request_and_generator.js'; export * from './shared.js'; @@ -95,6 +101,7 @@ export * from './trees/index.js'; export * from './tx_context.js'; export * from './tx_request.js'; export * from './verification_key.js'; +export * from './vk_witness_data.js'; export { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; export * from '@aztec/foundation/aztec-address'; diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts deleted file mode 100644 index 234b949acf7c..000000000000 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { makeTuple } from '@aztec/foundation/array'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; - -import { RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; -import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; -import { type UInt32 } from '../shared.js'; -import { VerificationKeyData } from '../verification_key.js'; -import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; - -// TODO: less ambiguous name -export class KernelData { - constructor( - /** - * Public inputs of the previous kernel. - */ - public publicInputs: KernelCircuitPublicInputs, - /** - * The previous kernel's proof (may be a tube proof or public kernel proof). - */ - public proof: RecursiveProof, - /** - * Verification key of the previous kernel. - */ - public vk: VerificationKeyData, - /** - * Index of the previous kernel's vk in a tree of vks. - */ - public vkIndex: UInt32, - /** - * Sibling path of the previous kernel's vk in a tree of vks. - */ - public vkPath: Tuple, - ) {} - - static empty(): KernelData { - return new this( - KernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), - 0, - makeTuple(VK_TREE_HEIGHT, Fr.zero), - ); - } - - static fromBuffer(buffer: Buffer | BufferReader): KernelData { - const reader = BufferReader.asReader(buffer); - return new this( - reader.readObject(KernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), - reader.readObject(VerificationKeyData), - reader.readNumber(), - reader.readArray(VK_TREE_HEIGHT, Fr), - ); - } - - toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath); - } -} diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts index 87e1f7b36095..43c58a54fc6d 100644 --- a/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts @@ -37,10 +37,10 @@ export class RootParityInput { return [fields.proof, fields.verificationKey, fields.vkPath, fields.publicInputs] as const; } - static fromBuffer( + static fromBuffer( buffer: Buffer | BufferReader, expectedSize?: PROOF_LENGTH, - ): RootParityInput { + ): RootParityInput { const reader = BufferReader.asReader(buffer); return new RootParityInput( RecursiveProof.fromBuffer(reader, expectedSize), @@ -50,10 +50,10 @@ export class RootParityInput { ); } - static fromString( + static fromString( str: string, expectedSize?: PROOF_LENGTH, - ): RootParityInput { + ): RootParityInput { return RootParityInput.fromBuffer(Buffer.from(str, 'hex'), expectedSize); } } diff --git a/yarn-project/circuits.js/src/structs/recursive_proof.ts b/yarn-project/circuits.js/src/structs/recursive_proof.ts index 4f94adbe212b..d368c267abb6 100644 --- a/yarn-project/circuits.js/src/structs/recursive_proof.ts +++ b/yarn-project/circuits.js/src/structs/recursive_proof.ts @@ -1,6 +1,6 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { Proof, makeEmptyProof } from './proof.js'; @@ -19,7 +19,7 @@ export class RecursiveProof { /** * Holds the serialized proof data in an array of fields, this is without the public inputs */ - public proof: Tuple, + public proof: Fr[], /** * Holds the serialized proof data in a binary buffer, this contains the public inputs @@ -29,7 +29,12 @@ export class RecursiveProof { * This flag determines if the 'proof' member is valid, or if we need to generate it from the 'binaryProof' first */ public fieldsValid: boolean, - ) {} + public proofLength: N, + ) { + if (proof.length !== proofLength) { + throw new Error(`Proof length ${proof.length} does not match expected length ${proofLength}.`); + } + } /** * Create a Proof from a Buffer or BufferReader. @@ -38,16 +43,18 @@ export class RecursiveProof { * @param buffer - A Buffer or BufferReader containing the length-encoded proof data. * @returns A Proof instance containing the decoded proof data. */ - static fromBuffer( - buffer: Buffer | BufferReader, - expectedSize?: N, - ): RecursiveProof { + static fromBuffer(buffer: Buffer | BufferReader, expectedSize?: N): RecursiveProof { const reader = BufferReader.asReader(buffer); const size = reader.readNumber(); if (typeof expectedSize === 'number' && expectedSize !== size) { throw new Error(`Expected proof length ${expectedSize}, got ${size}`); } - return new RecursiveProof(reader.readArray(size, Fr) as any, Proof.fromBuffer(reader), reader.readBoolean()); + return new RecursiveProof( + reader.readArray(size, Fr) as any, + Proof.fromBuffer(reader), + reader.readBoolean(), + size as N, + ); } /** @@ -73,10 +80,7 @@ export class RecursiveProof { * @param str - A hex string to deserialize from. * @returns - A new Proof instance. */ - static fromString( - str: string, - expectedSize?: N, - ): RecursiveProof { + static fromString(str: string, expectedSize?: N): RecursiveProof { return RecursiveProof.fromBuffer(Buffer.from(str, 'hex'), expectedSize); } } @@ -87,7 +91,7 @@ export class RecursiveProof { * @returns The empty "proof". */ export function makeEmptyRecursiveProof(size: N) { - return new RecursiveProof(makeTuple(size, Fr.zero), makeEmptyProof(), true); + return new RecursiveProof(makeTuple(size, Fr.zero), makeEmptyProof(), true, size); } export function makeRecursiveProof(size: PROOF_LENGTH, seed = 1) { @@ -95,6 +99,7 @@ export function makeRecursiveProof(size: PROOF_LENG makeTuple(size, (i: number) => new Fr(i), seed), makeEmptyProof(), true, + size, ); } @@ -103,5 +108,5 @@ export function makeRecursiveProof(size: PROOF_LENG * @returns The proof object */ export function makeRecursiveProofFromBinary(proof: Proof, size: PROOF_LENGTH) { - return new RecursiveProof(makeTuple(size, Fr.zero), proof, false); + return new RecursiveProof(makeTuple(size, Fr.zero), proof, false, size); } diff --git a/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts b/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts new file mode 100644 index 000000000000..11b8dd553fdd --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts @@ -0,0 +1,35 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { AVM_PROOF_LENGTH_IN_FIELDS } from '../../constants.gen.js'; +import { VMCircuitPublicInputs } from '../kernel/vm_circuit_public_inputs.js'; +import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; +import { VkWitnessData } from '../vk_witness_data.js'; + +export class AvmProofData { + constructor( + public publicInputs: VMCircuitPublicInputs, + public proof: RecursiveProof, + public vkData: VkWitnessData, + ) {} + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new AvmProofData( + reader.readObject(VMCircuitPublicInputs), + RecursiveProof.fromBuffer(reader), + reader.readObject(VkWitnessData), + ); + } + + toBuffer() { + return serializeToBuffer(this.publicInputs, this.proof, this.vkData); + } + + static empty() { + return new AvmProofData( + VMCircuitPublicInputs.empty(), + makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), + VkWitnessData.empty(), + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index d814dd1861ce..5081fa4879cf 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -3,7 +3,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { PartialStateReference } from '../partial_state_reference.js'; import { type RollupTypes } from '../shared.js'; -import { ConstantRollupData } from './base_rollup.js'; +import { ConstantRollupData } from './constant_rollup_data.js'; /** * Output of the base and merge rollup circuits. diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts deleted file mode 100644 index 6c0401f40747..000000000000 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { makeBaseRollupInputs } from '../../tests/factories.js'; -import { BaseRollupInputs } from './base_rollup.js'; - -describe('BaseRollupInputs', () => { - it('serializes to buffer and deserializes it back', () => { - const expected = makeBaseRollupInputs(); - const buffer = expected.toBuffer(); - const res = BaseRollupInputs.fromBuffer(buffer); - expect(res).toEqual(expected); - }); - - it('serializes to hex string and deserializes it back', () => { - const expected = makeBaseRollupInputs(); - const str = expected.toString(); - const res = BaseRollupInputs.fromString(str); - expect(res).toEqual(expected); - }); -}); diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts similarity index 51% rename from yarn-project/circuits.js/src/structs/rollup/base_rollup.ts rename to yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts index f77f65cc0a33..15364ffb636f 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts @@ -1,5 +1,4 @@ import { makeTuple } from '@aztec/foundation/array'; -import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -8,79 +7,22 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, } from '../../constants.gen.js'; -import { ClientIvcProof } from '../client_ivc_proof.js'; -import { GlobalVariables } from '../global_variables.js'; -import { KernelData } from '../kernel/kernel_data.js'; import { MembershipWitness } from '../membership_witness.js'; import { PartialStateReference } from '../partial_state_reference.js'; import { PublicDataHint } from '../public_data_hint.js'; import { type UInt32 } from '../shared.js'; import { PublicDataTreeLeaf, PublicDataTreeLeafPreimage } from '../trees/index.js'; -import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; +import { ConstantRollupData } from './constant_rollup_data.js'; import { StateDiffHints } from './state_diff_hints.js'; -/** - * Data which is forwarded through the base rollup circuits unchanged. - */ -export class ConstantRollupData { +export class BaseRollupHints { constructor( - /** Archive tree snapshot at the very beginning of the entire rollup. */ - public lastArchive: AppendOnlyTreeSnapshot, - /** - * Root of the verification key tree. - */ - public vkTreeRoot: Fr, - /** - * Root of the protocol contract tree. - */ - public protocolContractTreeRoot: Fr, - /** - * Global variables for the block - */ - public globalVariables: GlobalVariables, - ) {} - - static from(fields: FieldsOf): ConstantRollupData { - return new ConstantRollupData(...ConstantRollupData.getFields(fields)); - } - - static fromBuffer(buffer: Buffer | BufferReader): ConstantRollupData { - const reader = BufferReader.asReader(buffer); - return new ConstantRollupData( - reader.readObject(AppendOnlyTreeSnapshot), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - reader.readObject(GlobalVariables), - ); - } - - static getFields(fields: FieldsOf) { - return [fields.lastArchive, fields.vkTreeRoot, fields.protocolContractTreeRoot, fields.globalVariables] as const; - } - - static empty() { - return new ConstantRollupData(AppendOnlyTreeSnapshot.zero(), Fr.ZERO, Fr.ZERO, GlobalVariables.empty()); - } - - toBuffer() { - return serializeToBuffer(...ConstantRollupData.getFields(this)); - } -} - -/** - * Inputs to the base rollup circuit. - */ -export class BaseRollupInputs { - constructor( - /** Data of the 2 kernels that preceded this base rollup circuit. */ - public kernelData: KernelData, /** Partial state reference at the start of the rollup. */ public start: PartialStateReference, /** Hints used while proving state diff validity. */ public stateDiffHints: StateDiffHints, /** Public data read hint for accessing the balance of the fee payer. */ public feePayerFeeJuiceBalanceReadHint: PublicDataHint, - /** * The public data writes to be inserted in the tree, sorted high slot to low slot. */ @@ -106,7 +48,6 @@ export class BaseRollupInputs { MembershipWitness, typeof MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX >, - /** * Membership witnesses of blocks referred by each of the 2 kernels. */ @@ -117,13 +58,12 @@ export class BaseRollupInputs { public constants: ConstantRollupData, ) {} - static from(fields: FieldsOf): BaseRollupInputs { - return new BaseRollupInputs(...BaseRollupInputs.getFields(fields)); + static from(fields: FieldsOf): BaseRollupHints { + return new BaseRollupHints(...BaseRollupHints.getFields(fields)); } - static getFields(fields: FieldsOf) { + static getFields(fields: FieldsOf) { return [ - fields.kernelData, fields.start, fields.stateDiffHints, fields.feePayerFeeJuiceBalanceReadHint, @@ -141,7 +81,7 @@ export class BaseRollupInputs { * @returns The inputs serialized to a buffer. */ toBuffer() { - return serializeToBuffer(...BaseRollupInputs.getFields(this)); + return serializeToBuffer(...BaseRollupHints.getFields(this)); } /** @@ -152,15 +92,9 @@ export class BaseRollupInputs { return this.toBuffer().toString('hex'); } - /** - * Deserializes the inputs from a buffer. - * @param buffer - The buffer to deserialize from. - * @returns A new BaseRollupInputs instance. - */ - static fromBuffer(buffer: Buffer | BufferReader): BaseRollupInputs { + static fromBuffer(buffer: Buffer | BufferReader): BaseRollupHints { const reader = BufferReader.asReader(buffer); - return new BaseRollupInputs( - reader.readObject(KernelData), + return new BaseRollupHints( reader.readObject(PartialStateReference), reader.readObject(StateDiffHints), reader.readObject(PublicDataHint), @@ -175,18 +109,12 @@ export class BaseRollupInputs { ); } - /** - * Deserializes the inputs from a hex string. - * @param str - A hex string to deserialize from. - * @returns A new BaseRollupInputs instance. - */ static fromString(str: string) { - return BaseRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return BaseRollupHints.fromBuffer(Buffer.from(str, 'hex')); } static empty() { - return new BaseRollupInputs( - KernelData.empty(), + return new BaseRollupHints( PartialStateReference.empty(), StateDiffHints.empty(), PublicDataHint.empty(), @@ -199,57 +127,3 @@ export class BaseRollupInputs { ); } } - -export class TubeInputs { - constructor(public clientIVCData: ClientIvcProof) {} - - static from(fields: FieldsOf): TubeInputs { - return new TubeInputs(...TubeInputs.getFields(fields)); - } - - static getFields(fields: FieldsOf) { - return [fields.clientIVCData] as const; - } - - /** - * Serializes the inputs to a buffer. - * @returns The inputs serialized to a buffer. - */ - toBuffer() { - return serializeToBuffer(...TubeInputs.getFields(this)); - } - - /** - * Serializes the inputs to a hex string. - * @returns The instance serialized to a hex string. - */ - toString() { - return this.toBuffer().toString('hex'); - } - - /** - * Deserializes the inputs from a buffer. - * @param buffer - The buffer to deserialize from. - * @returns A new TubeInputs instance. - */ - static fromBuffer(buffer: Buffer | BufferReader): TubeInputs { - const reader = BufferReader.asReader(buffer); - return new TubeInputs(reader.readObject(ClientIvcProof)); - } - - isEmpty(): boolean { - return this.clientIVCData.isEmpty(); - } - /** - * Deserializes the inputs from a hex string. - * @param str - A hex string to deserialize from. - * @returns A new TubeInputs instance. - */ - static fromString(str: string) { - return TubeInputs.fromBuffer(Buffer.from(str, 'hex')); - } - - static empty() { - return new TubeInputs(ClientIvcProof.empty()); - } -} diff --git a/yarn-project/circuits.js/src/structs/rollup/constant_rollup_data.ts b/yarn-project/circuits.js/src/structs/rollup/constant_rollup_data.ts new file mode 100644 index 000000000000..5065e997097e --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/constant_rollup_data.ts @@ -0,0 +1,54 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { GlobalVariables } from '../global_variables.js'; +import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; + +/** + * Data which is forwarded through the base rollup circuits unchanged. + */ +export class ConstantRollupData { + constructor( + /** Archive tree snapshot at the very beginning of the entire rollup. */ + public lastArchive: AppendOnlyTreeSnapshot, + /** + * Root of the verification key tree. + */ + public vkTreeRoot: Fr, + /** + * Root of the protocol contract tree. + */ + public protocolContractTreeRoot: Fr, + /** + * Global variables for the block + */ + public globalVariables: GlobalVariables, + ) {} + + static from(fields: FieldsOf): ConstantRollupData { + return new ConstantRollupData(...ConstantRollupData.getFields(fields)); + } + + static fromBuffer(buffer: Buffer | BufferReader): ConstantRollupData { + const reader = BufferReader.asReader(buffer); + return new ConstantRollupData( + reader.readObject(AppendOnlyTreeSnapshot), + Fr.fromBuffer(reader), + Fr.fromBuffer(reader), + reader.readObject(GlobalVariables), + ); + } + + static getFields(fields: FieldsOf) { + return [fields.lastArchive, fields.vkTreeRoot, fields.protocolContractTreeRoot, fields.globalVariables] as const; + } + + static empty() { + return new ConstantRollupData(AppendOnlyTreeSnapshot.zero(), Fr.ZERO, Fr.ZERO, GlobalVariables.empty()); + } + + toBuffer() { + return serializeToBuffer(...ConstantRollupData.getFields(this)); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts new file mode 100644 index 000000000000..a5483c51e41a --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts @@ -0,0 +1,38 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { BaseRollupHints } from './base_rollup_hints.js'; +import { PrivateTubeData } from './private_tube_data.js'; + +export class PrivateBaseRollupInputs { + constructor(public tubeData: PrivateTubeData, public hints: BaseRollupHints) {} + + static from(fields: FieldsOf): PrivateBaseRollupInputs { + return new PrivateBaseRollupInputs(...PrivateBaseRollupInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.tubeData, fields.hints] as const; + } + + static fromBuffer(buffer: Buffer | BufferReader): PrivateBaseRollupInputs { + const reader = BufferReader.asReader(buffer); + return new PrivateBaseRollupInputs(reader.readObject(PrivateTubeData), reader.readObject(BaseRollupHints)); + } + + toBuffer() { + return serializeToBuffer(...PrivateBaseRollupInputs.getFields(this)); + } + + static fromString(str: string) { + return PrivateBaseRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + toString() { + return this.toBuffer().toString('hex'); + } + + static empty() { + return new PrivateBaseRollupInputs(PrivateTubeData.empty(), BaseRollupHints.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts b/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts new file mode 100644 index 000000000000..7fc0c3bc917c --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts @@ -0,0 +1,35 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { KernelCircuitPublicInputs } from '../kernel/kernel_circuit_public_inputs.js'; +import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; +import { VkWitnessData } from '../vk_witness_data.js'; + +export class PrivateTubeData { + constructor( + public publicInputs: KernelCircuitPublicInputs, + public proof: RecursiveProof, + public vkData: VkWitnessData, + ) {} + + static empty() { + return new PrivateTubeData( + KernelCircuitPublicInputs.empty(), + makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), + VkWitnessData.empty(), + ); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PrivateTubeData( + reader.readObject(KernelCircuitPublicInputs), + RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), + reader.readObject(VkWitnessData), + ); + } + + toBuffer() { + return serializeToBuffer(this.publicInputs, this.proof, this.vkData); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts new file mode 100644 index 000000000000..8c0f034c2c3a --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts @@ -0,0 +1,42 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { AvmProofData } from './avm_proof_data.js'; +import { BaseRollupHints } from './base_rollup_hints.js'; +import { PublicTubeData } from './public_tube_data.js'; + +export class PublicBaseRollupInputs { + constructor(public tubeData: PublicTubeData, public avmProofData: AvmProofData, public hints: BaseRollupHints) {} + + static from(fields: FieldsOf): PublicBaseRollupInputs { + return new PublicBaseRollupInputs(...PublicBaseRollupInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.tubeData, fields.avmProofData, fields.hints] as const; + } + + static fromBuffer(buffer: Buffer | BufferReader): PublicBaseRollupInputs { + const reader = BufferReader.asReader(buffer); + return new PublicBaseRollupInputs( + reader.readObject(PublicTubeData), + reader.readObject(AvmProofData), + reader.readObject(BaseRollupHints), + ); + } + + toBuffer() { + return serializeToBuffer(...PublicBaseRollupInputs.getFields(this)); + } + static fromString(str: string) { + return PublicBaseRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + toString() { + return this.toBuffer().toString('hex'); + } + + static empty() { + return new PublicBaseRollupInputs(PublicTubeData.empty(), AvmProofData.empty(), BaseRollupHints.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts new file mode 100644 index 000000000000..a71d0261c57d --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts @@ -0,0 +1,35 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { KernelCircuitPublicInputs } from '../kernel/kernel_circuit_public_inputs.js'; +import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; +import { VkWitnessData } from '../vk_witness_data.js'; + +export class PublicTubeData { + constructor( + public publicInputs: KernelCircuitPublicInputs, + public proof: RecursiveProof, + public vkData: VkWitnessData, + ) {} + + static empty() { + return new PublicTubeData( + KernelCircuitPublicInputs.empty(), + makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), + VkWitnessData.empty(), + ); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicTubeData( + reader.readObject(KernelCircuitPublicInputs), + RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), + reader.readObject(VkWitnessData), + ); + } + + toBuffer() { + return serializeToBuffer(this.publicInputs, this.proof, this.vkData); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts new file mode 100644 index 000000000000..840ced0fc0da --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts @@ -0,0 +1,58 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { ClientIvcProof } from '../client_ivc_proof.js'; + +export class TubeInputs { + constructor(public clientIVCData: ClientIvcProof) {} + + static from(fields: FieldsOf): TubeInputs { + return new TubeInputs(...TubeInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.clientIVCData] as const; + } + + /** + * Serializes the inputs to a buffer. + * @returns The inputs serialized to a buffer. + */ + toBuffer() { + return serializeToBuffer(...TubeInputs.getFields(this)); + } + + /** + * Serializes the inputs to a hex string. + * @returns The instance serialized to a hex string. + */ + toString() { + return this.toBuffer().toString('hex'); + } + + /** + * Deserializes the inputs from a buffer. + * @param buffer - The buffer to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromBuffer(buffer: Buffer | BufferReader): TubeInputs { + const reader = BufferReader.asReader(buffer); + return new TubeInputs(reader.readObject(ClientIvcProof)); + } + + isEmpty(): boolean { + return this.clientIVCData.isEmpty(); + } + /** + * Deserializes the inputs from a hex string. + * @param str - A hex string to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromString(str: string) { + return TubeInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + static empty() { + return new TubeInputs(ClientIvcProof.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/vk_witness_data.ts b/yarn-project/circuits.js/src/structs/vk_witness_data.ts new file mode 100644 index 000000000000..0ce5beb46f73 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/vk_witness_data.ts @@ -0,0 +1,38 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { VK_TREE_HEIGHT } from '../constants.gen.js'; +import { type UInt32 } from './shared.js'; +import { VerificationKeyData } from './verification_key.js'; + +export class VkWitnessData { + constructor( + public vk: VerificationKeyData, + /** + * Index of the vk in the vk tree. + */ + public vkIndex: UInt32, + /** + * Sibling path of the vk in the vk tree. + */ + public vkPath: Tuple, + ) {} + + static empty() { + return new VkWitnessData(VerificationKeyData.makeFakeHonk(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new VkWitnessData( + reader.readObject(VerificationKeyData), + reader.readNumber(), + reader.readArray(VK_TREE_HEIGHT, Fr), + ); + } + + toBuffer() { + return serializeToBuffer(this.vk, this.vkIndex, this.vkPath); + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 35b5300e31f6..25ecbebb469c 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -18,6 +18,7 @@ import { } from '../contract/index.js'; import { ARCHIVE_HEIGHT, + AVM_PROOF_LENGTH_IN_FIELDS, AZTEC_EPOCH_DURATION, AppendOnlyTreeSnapshot, AvmCircuitInputs, @@ -27,7 +28,6 @@ import { AvmKeyValueHint, BaseOrMergeRollupPublicInputs, BaseParityInputs, - BaseRollupInputs, CallContext, CombinedAccumulatedData, CombinedConstantData, @@ -152,13 +152,19 @@ import { GlobalVariables } from '../structs/global_variables.js'; import { Header } from '../structs/header.js'; import { AvmContractBytecodeHints, + AvmProofData, + BaseRollupHints, EnqueuedCallData, + PrivateBaseRollupInputs, + PrivateTubeData, PublicAccumulatedDataArrayLengths, + PublicBaseRollupInputs, PublicDataLeafHint, PublicInnerCallRequest, PublicKernelCircuitPrivateInputs, PublicKernelInnerCircuitPrivateInputs, PublicKernelInnerData, + PublicTubeData, PublicValidationRequestArrayLengths, PublicValidationRequests, ScopedL2ToL1Message, @@ -166,9 +172,9 @@ import { TreeLeafReadRequest, TreeLeafReadRequestHint, VMCircuitPublicInputs, + VkWitnessData, } from '../structs/index.js'; import { KernelCircuitPublicInputs } from '../structs/kernel/kernel_circuit_public_inputs.js'; -import { KernelData } from '../structs/kernel/kernel_data.js'; import { BlockMergeRollupInputs } from '../structs/rollup/block_merge_rollup.js'; import { BlockRootOrBlockMergePublicInputs, @@ -649,22 +655,6 @@ export function makePublicKernelData(seed = 1, kernelPublicInputs?: PublicKernel ); } -/** - * Makes arbitrary public kernel data. - * @param seed - The seed to use for generating the previous kernel data. - * @param kernelPublicInputs - The public kernel public inputs to use for generating the public kernel data. - * @returns A previous kernel data. - */ -export function makeRollupKernelData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs): KernelData { - return new KernelData( - kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), - makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x80), - VerificationKeyData.makeFakeHonk(), - 0x42, - makeTuple(VK_TREE_HEIGHT, fr, 0x1000), - ); -} - /** * Makes arbitrary proof. * @param seed - The seed to use for generating/mocking the proof. @@ -1239,14 +1229,19 @@ export function makeStateDiffHints(seed = 1): StateDiffHints { ); } -/** - * Makes arbitrary base rollup inputs. - * @param seed - The seed to use for generating the base rollup inputs. - * @returns A base rollup inputs. - */ -export function makeBaseRollupInputs(seed = 0): BaseRollupInputs { - const kernelData = makeRollupKernelData(seed); +function makeVkWitnessData(seed = 1) { + return new VkWitnessData(VerificationKeyData.makeFakeHonk(), seed, makeTuple(VK_TREE_HEIGHT, fr, seed + 0x100)); +} + +function makePrivateTubeData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs) { + return new PrivateTubeData( + kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), + makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x100), + makeVkWitnessData(seed + 0x200), + ); +} +function makeBaseRollupHints(seed = 1) { const start = makePartialStateReference(seed + 0x100); const stateDiffHints = makeStateDiffHints(seed + 0x600); @@ -1277,8 +1272,7 @@ export function makeBaseRollupInputs(seed = 0): BaseRollupInputs { const feePayerFeeJuiceBalanceReadHint = PublicDataHint.empty(); - return BaseRollupInputs.from({ - kernelData, + return BaseRollupHints.from({ start, stateDiffHints, sortedPublicDataWrites, @@ -1287,7 +1281,45 @@ export function makeBaseRollupInputs(seed = 0): BaseRollupInputs { lowPublicDataWritesMembershipWitnesses, archiveRootMembershipWitness, constants, - feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint, + feePayerFeeJuiceBalanceReadHint, + }); +} + +export function makePrivateBaseRollupInputs(seed = 0) { + const tubeData = makePrivateTubeData(seed); + const hints = makeBaseRollupHints(seed + 0x100); + + return PrivateBaseRollupInputs.from({ + tubeData, + hints, + }); +} + +function makePublicTubeData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs) { + return new PublicTubeData( + kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), + makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x100), + makeVkWitnessData(seed + 0x200), + ); +} + +function makeAvmProofData(seed = 1) { + return new AvmProofData( + makeVMCircuitPublicInputs(seed), + makeRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS, seed + 0x100), + makeVkWitnessData(seed + 0x200), + ); +} + +export function makePublicBaseRollupInputs(seed = 0) { + const tubeData = makePublicTubeData(seed); + const avmProofData = makeAvmProofData(seed + 0x100); + const hints = makeBaseRollupHints(seed + 0x100); + + return PublicBaseRollupInputs.from({ + tubeData, + avmProofData, + hints, }); } diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 2d06056b4083..347c5250b927 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -216,7 +216,7 @@ describe('L1Publisher integration', () => { seed + 0x500, ); - const processedTx = makeProcessedTx(tx, kernelOutput, []); + const processedTx = makeProcessedTx(tx, kernelOutput); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200); diff --git a/yarn-project/merkle-tree/src/standard_indexed_tree/test/standard_indexed_tree.test.ts b/yarn-project/merkle-tree/src/standard_indexed_tree/test/standard_indexed_tree.test.ts index 0ed6196c0e9e..d15aa61326ec 100644 --- a/yarn-project/merkle-tree/src/standard_indexed_tree/test/standard_indexed_tree.test.ts +++ b/yarn-project/merkle-tree/src/standard_indexed_tree/test/standard_indexed_tree.test.ts @@ -508,7 +508,7 @@ describe('StandardIndexedTreeSpecific', () => { const TREE_HEIGHT = 16; // originally from NULLIFIER_TREE_HEIGHT const INITIAL_TREE_SIZE = 8; // originally from INITIAL_NULLIFIER_TREE_SIZE - const SUBTREE_HEIGHT = 5; // originally from BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT + const SUBTREE_HEIGHT = 5; // originally from NULLIFIER_SUBTREE_HEIGHT // Create a depth-3 indexed merkle tree const appendTree = await createDb(openTmpStore(), pedersen, 'test', TREE_HEIGHT, INITIAL_TREE_SIZE); diff --git a/yarn-project/noir-protocol-circuits-types/src/artifacts.ts b/yarn-project/noir-protocol-circuits-types/src/artifacts.ts index 1e525e541a88..a31c70e51b88 100644 --- a/yarn-project/noir-protocol-circuits-types/src/artifacts.ts +++ b/yarn-project/noir-protocol-circuits-types/src/artifacts.ts @@ -14,14 +14,13 @@ import PrivateKernelTailJson from '../artifacts/private_kernel_tail.json' assert import PrivateKernelTailSimulatedJson from '../artifacts/private_kernel_tail_simulated.json' assert { type: 'json' }; import PrivateKernelTailToPublicJson from '../artifacts/private_kernel_tail_to_public.json' assert { type: 'json' }; import PrivateKernelTailToPublicSimulatedJson from '../artifacts/private_kernel_tail_to_public_simulated.json' assert { type: 'json' }; -import PublicKernelInnerJson from '../artifacts/public_kernel_inner.json' assert { type: 'json' }; import PublicKernelInnerSimulatedJson from '../artifacts/public_kernel_inner_simulated.json' assert { type: 'json' }; -import PublicKernelMergeJson from '../artifacts/public_kernel_merge.json' assert { type: 'json' }; import PublicKernelMergeSimulatedJson from '../artifacts/public_kernel_merge_simulated.json' assert { type: 'json' }; -import PublicKernelTailJson from '../artifacts/public_kernel_tail.json' assert { type: 'json' }; import PublicKernelTailSimulatedJson from '../artifacts/public_kernel_tail_simulated.json' assert { type: 'json' }; -import BaseRollupJson from '../artifacts/rollup_base.json' assert { type: 'json' }; -import BaseRollupSimulatedJson from '../artifacts/rollup_base_simulated.json' assert { type: 'json' }; +import PrivateBaseRollupJson from '../artifacts/rollup_base_private.json' assert { type: 'json' }; +import PrivateBaseRollupSimulatedJson from '../artifacts/rollup_base_private_simulated.json' assert { type: 'json' }; +import PublicBaseRollupJson from '../artifacts/rollup_base_public.json' assert { type: 'json' }; +import PublicBaseRollupSimulatedJson from '../artifacts/rollup_base_public_simulated.json' assert { type: 'json' }; import BlockMergeRollupJson from '../artifacts/rollup_block_merge.json' assert { type: 'json' }; import BlockRootRollupJson from '../artifacts/rollup_block_root.json' assert { type: 'json' }; import EmptyBlockRootRollupJson from '../artifacts/rollup_block_root_empty.json' assert { type: 'json' }; @@ -33,15 +32,18 @@ import { type PrivateResetArtifact, } from './private_kernel_reset_data.js'; +// To be deprecated. +export const SimulatedPublicKernelInnerArtifact = PublicKernelInnerSimulatedJson as NoirCompiledCircuit; +export const SimulatedPublicKernelMergeArtifact = PublicKernelMergeSimulatedJson as NoirCompiledCircuit; +export const SimulatedPublicKernelTailArtifact = PublicKernelTailSimulatedJson as NoirCompiledCircuit; + export type ServerProtocolArtifact = | 'EmptyNestedArtifact' | 'PrivateKernelEmptyArtifact' - | 'PublicKernelInnerArtifact' - | 'PublicKernelMergeArtifact' - | 'PublicKernelTailArtifact' | 'BaseParityArtifact' | 'RootParityArtifact' - | 'BaseRollupArtifact' + | 'PrivateBaseRollupArtifact' + | 'PublicBaseRollupArtifact' | 'MergeRollupArtifact' | 'BlockRootRollupArtifact' | 'EmptyBlockRootRollupArtifact' @@ -60,12 +62,10 @@ export type ProtocolArtifact = ServerProtocolArtifact | ClientProtocolArtifact; export const ServerCircuitArtifacts: Record = { EmptyNestedArtifact: EmptyNestedJson as NoirCompiledCircuit, PrivateKernelEmptyArtifact: PrivateKernelEmptyJson as NoirCompiledCircuit, - PublicKernelInnerArtifact: PublicKernelInnerJson as NoirCompiledCircuit, - PublicKernelMergeArtifact: PublicKernelMergeJson as NoirCompiledCircuit, - PublicKernelTailArtifact: PublicKernelTailJson as NoirCompiledCircuit, BaseParityArtifact: BaseParityJson as NoirCompiledCircuit, RootParityArtifact: RootParityJson as NoirCompiledCircuit, - BaseRollupArtifact: BaseRollupJson as NoirCompiledCircuit, + PrivateBaseRollupArtifact: PrivateBaseRollupJson as NoirCompiledCircuit, + PublicBaseRollupArtifact: PublicBaseRollupJson as NoirCompiledCircuit, MergeRollupArtifact: MergeRollupJson as NoirCompiledCircuit, BlockRootRollupArtifact: BlockRootRollupJson as NoirCompiledCircuit, EmptyBlockRootRollupArtifact: EmptyBlockRootRollupJson as NoirCompiledCircuit, @@ -76,12 +76,10 @@ export const ServerCircuitArtifacts: Record = { EmptyNestedArtifact: EmptyNestedSimulatedJson as NoirCompiledCircuit, PrivateKernelEmptyArtifact: PrivateKernelEmptySimulatedJson as NoirCompiledCircuit, - PublicKernelInnerArtifact: PublicKernelInnerSimulatedJson as NoirCompiledCircuit, - PublicKernelMergeArtifact: PublicKernelMergeSimulatedJson as NoirCompiledCircuit, - PublicKernelTailArtifact: PublicKernelTailSimulatedJson as NoirCompiledCircuit, BaseParityArtifact: BaseParityJson as NoirCompiledCircuit, RootParityArtifact: RootParityJson as NoirCompiledCircuit, - BaseRollupArtifact: BaseRollupSimulatedJson as NoirCompiledCircuit, + PrivateBaseRollupArtifact: PrivateBaseRollupSimulatedJson as NoirCompiledCircuit, + PublicBaseRollupArtifact: PublicBaseRollupSimulatedJson as NoirCompiledCircuit, MergeRollupArtifact: MergeRollupJson as NoirCompiledCircuit, BlockRootRollupArtifact: BlockRootRollupJson as NoirCompiledCircuit, EmptyBlockRootRollupArtifact: EmptyBlockRootRollupJson as NoirCompiledCircuit, diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index 6e39f70cb9e7..d592b373f222 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -1,7 +1,6 @@ import { type BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -10,6 +9,7 @@ import { type KernelCircuitPublicInputs, type MergeRollupInputs, type ParityPublicInputs, + type PrivateBaseRollupInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelEmptyInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -18,6 +18,7 @@ import { type PrivateKernelResetDimensions, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, + type PublicBaseRollupInputs, type PublicKernelCircuitPrivateInputs, type PublicKernelCircuitPublicInputs, type PublicKernelInnerCircuitPrivateInputs, @@ -39,13 +40,15 @@ import { ClientCircuitArtifacts, ServerCircuitArtifacts, SimulatedClientCircuitArtifacts, + SimulatedPublicKernelInnerArtifact, + SimulatedPublicKernelMergeArtifact, + SimulatedPublicKernelTailArtifact, SimulatedServerCircuitArtifacts, } from './artifacts.js'; import { type PrivateResetArtifact } from './private_kernel_reset_data.js'; import { mapBaseOrMergeRollupPublicInputsFromNoir, mapBaseParityInputsToNoir, - mapBaseRollupInputsToNoir, mapBlockMergeRollupInputsToNoir, mapBlockRootOrBlockMergePublicInputsFromNoir, mapBlockRootRollupInputsToNoir, @@ -55,6 +58,7 @@ import { mapKernelCircuitPublicInputsFromNoir, mapMergeRollupInputsToNoir, mapParityPublicInputsFromNoir, + mapPrivateBaseRollupInputsToNoir, mapPrivateCallDataToNoir, mapPrivateCircuitPublicInputsToNoir, mapPrivateKernelCircuitPublicInputsFromNoir, @@ -63,6 +67,7 @@ import { mapPrivateKernelResetHintsToNoir, mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir, mapPrivateKernelTailCircuitPublicInputsForRollupFromNoir, + mapPublicBaseRollupInputsToNoir, mapPublicKernelCircuitPrivateInputsToNoir, mapPublicKernelCircuitPublicInputsFromNoir, mapPublicKernelInnerCircuitPrivateInputsToNoir, @@ -74,21 +79,24 @@ import { mapVMCircuitPublicInputsFromNoir, } from './type_conversion.js'; import { - type ParityBaseReturnType as BaseParityReturnType, - type RollupBaseReturnType as BaseRollupReturnType, - type RollupBlockMergeReturnType as BlockMergeRollupReturnType, - type RollupBlockRootReturnType as BlockRootRollupReturnType, - type PrivateKernelInitReturnType as InitReturnType, - type PrivateKernelInnerReturnType as InnerReturnType, - type RollupMergeReturnType as MergeRollupReturnType, + type ParityBaseReturnType, + type ParityRootReturnType, type PrivateKernelEmptyReturnType, - type PublicKernelInnerReturnType, - type PublicKernelMergeReturnType, - type PrivateKernelResetReturnType as ResetReturnType, + type PrivateKernelInitReturnType, + type PrivateKernelInnerReturnType, + type PrivateKernelResetReturnType, + type PrivateKernelTailReturnType, + type PrivateKernelTailToPublicReturnType, + type PublicKernelInnerSimulatedReturnType, + type PublicKernelMergeSimulatedReturnType, + type PublicKernelTailSimulatedReturnType, + type RollupBasePrivateReturnType, + type RollupBasePublicReturnType, + type RollupBlockMergeReturnType, type RollupBlockRootEmptyReturnType, - type ParityRootReturnType as RootParityReturnType, - type RollupRootReturnType as RootRollupReturnType, - type PrivateKernelTailReturnType as TailReturnType, + type RollupBlockRootReturnType, + type RollupMergeReturnType, + type RollupRootReturnType, PrivateKernelInit as executePrivateKernelInitWithACVM, PrivateKernelInner as executePrivateKernelInnerWithACVM, PrivateKernelTailToPublic as executePrivateKernelTailToPublicWithACVM, @@ -354,7 +362,7 @@ export function convertPrivateKernelInitOutputsFromWitnessMap(outputs: WitnessMa const decodedInputs: DecodedInputs = abiDecode(ClientCircuitArtifacts.PrivateKernelInitArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as InitReturnType; + const returnType = decodedInputs.return_value as PrivateKernelInitReturnType; return mapPrivateKernelCircuitPublicInputsFromNoir(returnType); } @@ -369,7 +377,7 @@ export function convertPrivateKernelInnerOutputsFromWitnessMap(outputs: WitnessM const decodedInputs: DecodedInputs = abiDecode(ClientCircuitArtifacts.PrivateKernelInnerArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as InnerReturnType; + const returnType = decodedInputs.return_value as PrivateKernelInnerReturnType; return mapPrivateKernelCircuitPublicInputsFromNoir(returnType); } @@ -388,7 +396,7 @@ export function convertPrivateKernelResetOutputsFromWitnessMap( const decodedInputs: DecodedInputs = abiDecode(artifact.abi as Abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as ResetReturnType; + const returnType = decodedInputs.return_value as PrivateKernelResetReturnType; return mapPrivateKernelCircuitPublicInputsFromNoir(returnType); } @@ -405,7 +413,7 @@ export function convertPrivateKernelTailOutputsFromWitnessMap( const decodedInputs: DecodedInputs = abiDecode(ClientCircuitArtifacts.PrivateKernelTailArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as TailReturnType; + const returnType = decodedInputs.return_value as PrivateKernelTailReturnType; return mapPrivateKernelTailCircuitPublicInputsForRollupFromNoir(returnType); } @@ -422,7 +430,7 @@ export function convertPrivateKernelTailForPublicOutputsFromWitnessMap( const decodedInputs: DecodedInputs = abiDecode(ClientCircuitArtifacts.PrivateKernelTailToPublicArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as PublicKernelMergeReturnType; + const returnType = decodedInputs.return_value as PrivateKernelTailToPublicReturnType; return mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir(returnType); } @@ -449,31 +457,35 @@ export function convertRootParityInputsToWitnessMap(inputs: RootParityInputs): W return initialWitnessMap; } -/** - * Converts the inputs of the base rollup circuit into a witness map. - * @param inputs - The base rollup inputs. - * @returns The witness map - */ -export function convertBaseRollupInputsToWitnessMap(inputs: BaseRollupInputs): WitnessMap { - const mapped = mapBaseRollupInputsToNoir(inputs); - const initialWitnessMap = abiEncode(ServerCircuitArtifacts.BaseRollupArtifact.abi, { inputs: mapped as any }); - return initialWitnessMap; -} - export function convertPrivateKernelEmptyInputsToWitnessMap(inputs: PrivateKernelEmptyInputs): WitnessMap { const mapped = mapEmptyKernelInputsToNoir(inputs); const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PrivateKernelEmptyArtifact.abi, { input: mapped as any }); return initialWitnessMap; } -/** - * Converts the inputs of the simulated base rollup circuit into a witness map. - * @param inputs - The base rollup inputs. - * @returns The witness map - */ -export function convertSimulatedBaseRollupInputsToWitnessMap(inputs: BaseRollupInputs): WitnessMap { - const mapped = mapBaseRollupInputsToNoir(inputs); - const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.BaseRollupArtifact.abi, { +export function convertPrivateBaseRollupInputsToWitnessMap(inputs: PrivateBaseRollupInputs): WitnessMap { + const mapped = mapPrivateBaseRollupInputsToNoir(inputs); + const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PrivateBaseRollupArtifact.abi, { inputs: mapped as any }); + return initialWitnessMap; +} + +export function convertSimulatedPrivateBaseRollupInputsToWitnessMap(inputs: PrivateBaseRollupInputs): WitnessMap { + const mapped = mapPrivateBaseRollupInputsToNoir(inputs); + const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.PrivateBaseRollupArtifact.abi, { + inputs: mapped as any, + }); + return initialWitnessMap; +} + +export function convertPublicBaseRollupInputsToWitnessMap(inputs: PublicBaseRollupInputs): WitnessMap { + const mapped = mapPublicBaseRollupInputsToNoir(inputs); + const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PublicBaseRollupArtifact.abi, { inputs: mapped as any }); + return initialWitnessMap; +} + +export function convertSimulatedPublicBaseRollupInputsToWitnessMap(inputs: PublicBaseRollupInputs): WitnessMap { + const mapped = mapPublicBaseRollupInputsToNoir(inputs); + const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.PublicBaseRollupArtifact.abi, { inputs: mapped as any, }); return initialWitnessMap; @@ -545,7 +557,7 @@ export function convertSimulatedPublicInnerInputsToWitnessMap( inputs: PublicKernelInnerCircuitPrivateInputs, ): WitnessMap { const mapped = mapPublicKernelInnerCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.PublicKernelInnerArtifact.abi, { + const initialWitnessMap = abiEncode(SimulatedPublicKernelInnerArtifact.abi, { input: mapped as any, }); return initialWitnessMap; @@ -558,7 +570,7 @@ export function convertSimulatedPublicInnerInputsToWitnessMap( */ export function convertSimulatedPublicMergeInputsToWitnessMap(inputs: PublicKernelCircuitPrivateInputs): WitnessMap { const mapped = mapPublicKernelCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.PublicKernelMergeArtifact.abi, { + const initialWitnessMap = abiEncode(SimulatedPublicKernelMergeArtifact.abi, { input: mapped as any, }); return initialWitnessMap; @@ -571,49 +583,12 @@ export function convertSimulatedPublicMergeInputsToWitnessMap(inputs: PublicKern */ export function convertSimulatedPublicTailInputsToWitnessMap(inputs: PublicKernelTailCircuitPrivateInputs): WitnessMap { const mapped = mapPublicKernelTailCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(SimulatedServerCircuitArtifacts.PublicKernelTailArtifact.abi, { - input: mapped as any, - }); - return initialWitnessMap; -} - -/** - * Converts the inputs of the public inner circuit into a witness map - * @param inputs - The public kernel inputs. - * @returns The witness map - */ -export function convertPublicInnerInputsToWitnessMap(inputs: PublicKernelInnerCircuitPrivateInputs): WitnessMap { - const mapped = mapPublicKernelInnerCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PublicKernelInnerArtifact.abi, { + const initialWitnessMap = abiEncode(SimulatedPublicKernelTailArtifact.abi, { input: mapped as any, }); return initialWitnessMap; } -/** - * Converts the inputs of the public merge circuit into a witness map - * @param inputs - The public kernel inputs. - * @returns The witness map - */ -export function convertPublicMergeInputsToWitnessMap(inputs: PublicKernelCircuitPrivateInputs): WitnessMap { - const mapped = mapPublicKernelCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PublicKernelMergeArtifact.abi, { - input: mapped as any, - }); - return initialWitnessMap; -} - -/** - * Converts the inputs of the public tail circuit into a witness map - * @param inputs - The public kernel inputs. - * @returns The witness map - */ -export function convertPublicTailInputsToWitnessMap(inputs: PublicKernelTailCircuitPrivateInputs): WitnessMap { - const mapped = mapPublicKernelTailCircuitPrivateInputsToNoir(inputs); - const initialWitnessMap = abiEncode(ServerCircuitArtifacts.PublicKernelTailArtifact.abi, { input: mapped as any }); - return initialWitnessMap; -} - export function convertPrivateKernelEmptyOutputsFromWitnessMap(outputs: WitnessMap): KernelCircuitPublicInputs { const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PrivateKernelEmptyArtifact.abi, outputs); const returnType = decodedInputs.return_value as PrivateKernelEmptyReturnType; @@ -638,12 +613,49 @@ export function convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap( * @param outputs - The base rollup outputs as a witness map. * @returns The public inputs. */ -export function convertSimulatedBaseRollupOutputsFromWitnessMap(outputs: WitnessMap): BaseOrMergeRollupPublicInputs { +export function convertSimulatedPrivateBaseRollupOutputsFromWitnessMap( + outputs: WitnessMap, +): BaseOrMergeRollupPublicInputs { + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode( + SimulatedServerCircuitArtifacts.PrivateBaseRollupArtifact.abi, + outputs, + ); + + // Cast the inputs as the return type + const returnType = decodedInputs.return_value as RollupBasePrivateReturnType; + + return mapBaseOrMergeRollupPublicInputsFromNoir(returnType); +} + +/** + * Converts the outputs of the base rollup circuit from a witness map. + * @param outputs - The base rollup outputs as a witness map. + * @returns The public inputs. + */ +export function convertPrivateBaseRollupOutputsFromWitnessMap(outputs: WitnessMap): BaseOrMergeRollupPublicInputs { + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PrivateBaseRollupArtifact.abi, outputs); + + // Cast the inputs as the return type + const returnType = decodedInputs.return_value as RollupBasePrivateReturnType; + + return mapBaseOrMergeRollupPublicInputsFromNoir(returnType); +} + +/** + * Converts the outputs of the simulated base rollup circuit from a witness map. + * @param outputs - The base rollup outputs as a witness map. + * @returns The public inputs. + */ +export function convertSimulatedPublicBaseRollupOutputsFromWitnessMap( + outputs: WitnessMap, +): BaseOrMergeRollupPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(SimulatedServerCircuitArtifacts.BaseRollupArtifact.abi, outputs); + const decodedInputs: DecodedInputs = abiDecode(SimulatedServerCircuitArtifacts.PublicBaseRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as BaseRollupReturnType; + const returnType = decodedInputs.return_value as RollupBasePublicReturnType; return mapBaseOrMergeRollupPublicInputsFromNoir(returnType); } @@ -653,12 +665,12 @@ export function convertSimulatedBaseRollupOutputsFromWitnessMap(outputs: Witness * @param outputs - The base rollup outputs as a witness map. * @returns The public inputs. */ -export function convertBaseRollupOutputsFromWitnessMap(outputs: WitnessMap): BaseOrMergeRollupPublicInputs { +export function convertPublicBaseRollupOutputsFromWitnessMap(outputs: WitnessMap): BaseOrMergeRollupPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.BaseRollupArtifact.abi, outputs); + const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PublicBaseRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as BaseRollupReturnType; + const returnType = decodedInputs.return_value as RollupBasePublicReturnType; return mapBaseOrMergeRollupPublicInputsFromNoir(returnType); } @@ -673,7 +685,7 @@ export function convertMergeRollupOutputsFromWitnessMap(outputs: WitnessMap): Ba const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.MergeRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as MergeRollupReturnType; + const returnType = decodedInputs.return_value as RollupMergeReturnType; return mapBaseOrMergeRollupPublicInputsFromNoir(returnType); } @@ -705,7 +717,7 @@ export function convertBlockRootRollupOutputsFromWitnessMap(outputs: WitnessMap) const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.BlockRootRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as BlockRootRollupReturnType; + const returnType = decodedInputs.return_value as RollupBlockRootReturnType; return mapBlockRootOrBlockMergePublicInputsFromNoir(returnType); } @@ -720,7 +732,7 @@ export function convertBlockMergeRollupOutputsFromWitnessMap(outputs: WitnessMap const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.BlockMergeRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as BlockMergeRollupReturnType; + const returnType = decodedInputs.return_value as RollupBlockMergeReturnType; return mapBlockRootOrBlockMergePublicInputsFromNoir(returnType); } @@ -735,7 +747,7 @@ export function convertRootRollupOutputsFromWitnessMap(outputs: WitnessMap): Roo const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.RootRollupArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as RootRollupReturnType; + const returnType = decodedInputs.return_value as RollupRootReturnType; return mapRootRollupPublicInputsFromNoir(returnType); } @@ -750,7 +762,7 @@ export function convertBaseParityOutputsFromWitnessMap(outputs: WitnessMap): Par const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.BaseParityArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as BaseParityReturnType; + const returnType = decodedInputs.return_value as ParityBaseReturnType; return mapParityPublicInputsFromNoir(returnType); } @@ -765,7 +777,7 @@ export function convertRootParityOutputsFromWitnessMap(outputs: WitnessMap): Par const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.RootParityArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as RootParityReturnType; + const returnType = decodedInputs.return_value as ParityRootReturnType; return mapParityPublicInputsFromNoir(returnType); } @@ -777,13 +789,10 @@ export function convertRootParityOutputsFromWitnessMap(outputs: WitnessMap): Par */ export function convertSimulatedPublicInnerOutputFromWitnessMap(outputs: WitnessMap): VMCircuitPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode( - SimulatedServerCircuitArtifacts.PublicKernelInnerArtifact.abi, - outputs, - ); + const decodedInputs: DecodedInputs = abiDecode(SimulatedPublicKernelInnerArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as PublicKernelInnerReturnType; + const returnType = decodedInputs.return_value as PublicKernelInnerSimulatedReturnType; return mapVMCircuitPublicInputsFromNoir(returnType); } @@ -795,13 +804,10 @@ export function convertSimulatedPublicInnerOutputFromWitnessMap(outputs: Witness */ export function convertSimulatedPublicMergeOutputFromWitnessMap(outputs: WitnessMap): PublicKernelCircuitPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode( - SimulatedServerCircuitArtifacts.PublicKernelMergeArtifact.abi, - outputs, - ); + const decodedInputs: DecodedInputs = abiDecode(SimulatedPublicKernelMergeArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as PublicKernelMergeReturnType; + const returnType = decodedInputs.return_value as PublicKernelMergeSimulatedReturnType; return mapPublicKernelCircuitPublicInputsFromNoir(returnType); } @@ -813,55 +819,10 @@ export function convertSimulatedPublicMergeOutputFromWitnessMap(outputs: Witness */ export function convertSimulatedPublicTailOutputFromWitnessMap(outputs: WitnessMap): KernelCircuitPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(SimulatedServerCircuitArtifacts.PublicKernelTailArtifact.abi, outputs); - - // Cast the inputs as the return type - const returnType = decodedInputs.return_value as TailReturnType; - - return mapKernelCircuitPublicInputsFromNoir(returnType); -} - -/** - * Converts the outputs of the public inner circuit from a witness map. - * @param outputs - The public kernel outputs as a witness map. - * @returns The public inputs. - */ -export function convertPublicInnerOutputFromWitnessMap(outputs: WitnessMap): VMCircuitPublicInputs { - // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PublicKernelInnerArtifact.abi, outputs); - - // Cast the inputs as the return type - const returnType = decodedInputs.return_value as PublicKernelInnerReturnType; - - return mapVMCircuitPublicInputsFromNoir(returnType); -} - -/** - * Converts the outputs of the public merge circuit from a witness map. - * @param outputs - The public kernel outputs as a witness map. - * @returns The public inputs. - */ -export function convertPublicMergeOutputFromWitnessMap(outputs: WitnessMap): PublicKernelCircuitPublicInputs { - // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PublicKernelMergeArtifact.abi, outputs); - - // Cast the inputs as the return type - const returnType = decodedInputs.return_value as PublicKernelMergeReturnType; - - return mapPublicKernelCircuitPublicInputsFromNoir(returnType); -} - -/** - * Converts the outputs of the public tail circuit from a witness map. - * @param outputs - The public kernel outputs as a witness map. - * @returns The public inputs. - */ -export function convertPublicTailOutputFromWitnessMap(outputs: WitnessMap): KernelCircuitPublicInputs { - // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(ServerCircuitArtifacts.PublicKernelTailArtifact.abi, outputs); + const decodedInputs: DecodedInputs = abiDecode(SimulatedPublicKernelTailArtifact.abi, outputs); // Cast the inputs as the return type - const returnType = decodedInputs.return_value as TailReturnType; + const returnType = decodedInputs.return_value as PublicKernelTailSimulatedReturnType; return mapKernelCircuitPublicInputsFromNoir(returnType); } diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts index 7d437c85ff76..550e09f800c4 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts @@ -15,10 +15,11 @@ const circuits = [ 'private_kernel_reset', 'private_kernel_tail', 'private_kernel_tail_to_public', - 'public_kernel_inner', - 'public_kernel_merge', - 'public_kernel_tail', - 'rollup_base', + 'public_kernel_inner_simulated', + 'public_kernel_merge_simulated', + 'public_kernel_tail_simulated', + 'rollup_base_private', + 'rollup_base_public', 'rollup_merge', 'rollup_block_root', 'rollup_block_merge', diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 2e355682fd38..0d1d9fd80374 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1,10 +1,12 @@ import { + type AVM_PROOF_LENGTH_IN_FIELDS, + AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, AZTEC_EPOCH_DURATION, AppendOnlyTreeSnapshot, + type AvmProofData, AztecAddress, BaseOrMergeRollupPublicInputs, type BaseParityInputs, - type BaseRollupInputs, type BlockMergeRollupInputs, BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -33,7 +35,6 @@ import { HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, Header, KernelCircuitPublicInputs, - type KernelData, type KeyValidationHint, KeyValidationRequest, KeyValidationRequestAndGenerator, @@ -81,6 +82,7 @@ import { type PreviousRollupBlockData, type PreviousRollupData, PrivateAccumulatedData, + type PrivateBaseRollupInputs, type PrivateCallData, PrivateCallRequest, type PrivateCircuitPublicInputs, @@ -89,9 +91,11 @@ import { type PrivateKernelEmptyInputs, type PrivateKernelResetHints, PrivateKernelTailCircuitPublicInputs, + type PrivateTubeData, PrivateValidationRequests, PublicAccumulatedData, PublicAccumulatedDataArrayLengths, + type PublicBaseRollupInputs, type PublicCallData, PublicCallRequest, PublicCallStackItemCompressed, @@ -110,6 +114,7 @@ import { type PublicKernelInnerData, type PublicKernelTailCircuitPrivateInputs, type PublicKeys, + type PublicTubeData, PublicValidationRequestArrayLengths, PublicValidationRequests, type RECURSIVE_PROOF_LENGTH, @@ -132,6 +137,7 @@ import { type SettledReadHint, type StateDiffHints, StateReference, + type TUBE_PROOF_LENGTH, type TransientDataIndexHint, TreeLeafReadRequest, type TreeLeafReadRequestHint, @@ -139,15 +145,16 @@ import { type TxRequest, VMCircuitPublicInputs, type VerificationKeyAsFields, + type VkWitnessData, } from '@aztec/circuits.js'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { type Tuple, mapTuple, toTruncField } from '@aztec/foundation/serialize'; import type { AppendOnlyTreeSnapshot as AppendOnlyTreeSnapshotNoir, + AvmProofData as AvmProofDataNoir, BaseOrMergeRollupPublicInputs as BaseOrMergeRollupPublicInputsNoir, BaseParityInputs as BaseParityInputsNoir, - BaseRollupInputs as BaseRollupInputsNoir, BlockMergeRollupInputs as BlockMergeRollupInputsNoir, BlockRootOrBlockMergePublicInputs as BlockRootOrBlockMergePublicInputsNoir, BlockRootRollupInputs as BlockRootRollupInputsNoir, @@ -172,7 +179,6 @@ import type { EmbeddedCurveScalar as GrumpkinScalarNoir, Header as HeaderNoir, KernelCircuitPublicInputs as KernelCircuitPublicInputsNoir, - KernelData as KernelDataNoir, KeyValidationHint as KeyValidationHintNoir, KeyValidationRequestAndGenerator as KeyValidationRequestAndGeneratorNoir, KeyValidationRequest as KeyValidationRequestsNoir, @@ -204,6 +210,7 @@ import type { PreviousRollupBlockData as PreviousRollupBlockDataNoir, PreviousRollupData as PreviousRollupDataNoir, PrivateAccumulatedData as PrivateAccumulatedDataNoir, + PrivateBaseRollupInputs as PrivateBaseRollupInputsNoir, PrivateCallDataWithoutPublicInputs as PrivateCallDataWithoutPublicInputsNoir, PrivateCallRequest as PrivateCallRequestNoir, PrivateCircuitPublicInputs as PrivateCircuitPublicInputsNoir, @@ -211,9 +218,11 @@ import type { PrivateKernelDataWithoutPublicInputs as PrivateKernelDataWithoutPublicInputsNoir, PrivateKernelEmptyPrivateInputs as PrivateKernelEmptyPrivateInputsNoir, PrivateKernelResetHints as PrivateKernelResetHintsNoir, + PrivateTubeData as PrivateTubeDataNoir, PrivateValidationRequests as PrivateValidationRequestsNoir, PublicAccumulatedDataArrayLengths as PublicAccumulatedDataArrayLengthsNoir, PublicAccumulatedData as PublicAccumulatedDataNoir, + PublicBaseRollupInputs as PublicBaseRollupInputsNoir, PublicCallData as PublicCallDataNoir, PublicCallRequest as PublicCallRequestNoir, PublicCallStackItemCompressed as PublicCallStackItemCompressedNoir, @@ -232,6 +241,7 @@ import type { PublicKernelMergeCircuitPrivateInputs as PublicKernelMergeCircuitPrivateInputsNoir, PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, PublicKeys as PublicKeysNoir, + PublicTubeData as PublicTubeDataNoir, PublicValidationRequestArrayLengths as PublicValidationRequestArrayLengthsNoir, PublicValidationRequests as PublicValidationRequestsNoir, ReadRequest as ReadRequestNoir, @@ -259,6 +269,7 @@ import type { TxRequest as TxRequestNoir, VMCircuitPublicInputs as VMCircuitPublicInputsNoir, VerificationKey as VerificationKeyNoir, + VkData as VkDataNoir, } from './types/index.js'; /* eslint-disable camelcase */ @@ -1641,16 +1652,6 @@ function mapPublicKernelInnerDataToNoir(publicKernelData: PublicKernelInnerData) }; } -function mapKernelDataToNoir(kernelData: KernelData): KernelDataNoir { - return { - public_inputs: mapKernelCircuitPublicInputsToNoir(kernelData.publicInputs), - proof: mapRecursiveProofToNoir(kernelData.proof), - vk: mapVerificationKeyToNoir(kernelData.vk.keyAsFields, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), - vk_index: mapFieldToNoir(new Fr(kernelData.vkIndex)), - vk_path: mapTuple(kernelData.vkPath, mapFieldToNoir), - }; -} - export function mapVerificationKeyToNoir( key: VerificationKeyAsFields, length: N, @@ -1664,6 +1665,14 @@ export function mapVerificationKeyToNoir( }; } +function mapVkWitnessDataToNoir(vkData: VkWitnessData, length: N): VkDataNoir { + return { + vk: mapVerificationKeyToNoir(vkData.vk.keyAsFields, length), + vk_index: mapFieldToNoir(new Fr(vkData.vkIndex)), + vk_path: mapTuple(vkData.vkPath, mapFieldToNoir), + }; +} + export function mapPrivateKernelCircuitPublicInputsFromNoir( inputs: PrivateKernelCircuitPublicInputsNoir, ): PrivateKernelCircuitPublicInputs { @@ -2263,7 +2272,7 @@ export function mapRootRollupInputsToNoir(rootRollupInputs: RootRollupInputs): R export function mapRecursiveProofToNoir(proof: RecursiveProof) { return { - fields: mapTuple(proof.proof, mapFieldToNoir), + fields: mapTuple(proof.proof, mapFieldToNoir) as FixedLengthArray, }; } @@ -2548,31 +2557,87 @@ export function mapRootParityInputsToNoir(inputs: RootParityInputs): RootParityI }; } +function mapPrivateTubeDataToNoir(data: PrivateTubeData): PrivateTubeDataNoir { + return { + public_inputs: mapKernelCircuitPublicInputsToNoir(data.publicInputs), + proof: mapRecursiveProofToNoir(data.proof), + vk_data: mapVkWitnessDataToNoir(data.vkData, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + }; +} + /** * Maps the inputs to the base rollup to noir. * @param input - The circuits.js base rollup inputs. * @returns The noir base rollup inputs. */ -export function mapBaseRollupInputsToNoir(inputs: BaseRollupInputs): BaseRollupInputsNoir { +export function mapPrivateBaseRollupInputsToNoir(inputs: PrivateBaseRollupInputs): PrivateBaseRollupInputsNoir { + return { + tube_data: mapPrivateTubeDataToNoir(inputs.tubeData), + + start: mapPartialStateReferenceToNoir(inputs.hints.start), + state_diff_hints: mapStateDiffHintsToNoir(inputs.hints.stateDiffHints), + + sorted_public_data_writes: mapTuple(inputs.hints.sortedPublicDataWrites, mapPublicDataTreeLeafToNoir), + + sorted_public_data_writes_indexes: mapTuple(inputs.hints.sortedPublicDataWritesIndexes, mapNumberToNoir), + + low_public_data_writes_preimages: mapTuple( + inputs.hints.lowPublicDataWritesPreimages, + mapPublicDataTreePreimageToNoir, + ), + + low_public_data_writes_witnesses: mapTuple( + inputs.hints.lowPublicDataWritesMembershipWitnesses, + (witness: MembershipWitness) => mapMembershipWitnessToNoir(witness), + ), + + archive_root_membership_witness: mapMembershipWitnessToNoir(inputs.hints.archiveRootMembershipWitness), + constants: mapConstantRollupDataToNoir(inputs.hints.constants), + fee_payer_fee_juice_balance_read_hint: mapPublicDataHintToNoir(inputs.hints.feePayerFeeJuiceBalanceReadHint), + }; +} + +function mapPublicTubeDataToNoir(data: PublicTubeData): PublicTubeDataNoir { + return { + public_inputs: mapKernelCircuitPublicInputsToNoir(data.publicInputs), + proof: mapRecursiveProofToNoir(data.proof), + vk_data: mapVkWitnessDataToNoir(data.vkData, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + }; +} + +function mapAvmProofDataToNoir(data: AvmProofData): AvmProofDataNoir { return { - kernel_data: mapKernelDataToNoir(inputs.kernelData), - start: mapPartialStateReferenceToNoir(inputs.start), - state_diff_hints: mapStateDiffHintsToNoir(inputs.stateDiffHints), + public_inputs: mapVMCircuitPublicInputsToNoir(data.publicInputs), + proof: mapRecursiveProofToNoir(data.proof), + vk_data: mapVkWitnessDataToNoir(data.vkData, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS), + }; +} - sorted_public_data_writes: mapTuple(inputs.sortedPublicDataWrites, mapPublicDataTreeLeafToNoir), +export function mapPublicBaseRollupInputsToNoir(inputs: PublicBaseRollupInputs): PublicBaseRollupInputsNoir { + return { + tube_data: mapPublicTubeDataToNoir(inputs.tubeData), + avm_proof_data: mapAvmProofDataToNoir(inputs.avmProofData), + + start: mapPartialStateReferenceToNoir(inputs.hints.start), + state_diff_hints: mapStateDiffHintsToNoir(inputs.hints.stateDiffHints), - sorted_public_data_writes_indexes: mapTuple(inputs.sortedPublicDataWritesIndexes, mapNumberToNoir), + sorted_public_data_writes: mapTuple(inputs.hints.sortedPublicDataWrites, mapPublicDataTreeLeafToNoir), - low_public_data_writes_preimages: mapTuple(inputs.lowPublicDataWritesPreimages, mapPublicDataTreePreimageToNoir), + sorted_public_data_writes_indexes: mapTuple(inputs.hints.sortedPublicDataWritesIndexes, mapNumberToNoir), + + low_public_data_writes_preimages: mapTuple( + inputs.hints.lowPublicDataWritesPreimages, + mapPublicDataTreePreimageToNoir, + ), low_public_data_writes_witnesses: mapTuple( - inputs.lowPublicDataWritesMembershipWitnesses, + inputs.hints.lowPublicDataWritesMembershipWitnesses, (witness: MembershipWitness) => mapMembershipWitnessToNoir(witness), ), - archive_root_membership_witness: mapMembershipWitnessToNoir(inputs.archiveRootMembershipWitness), - constants: mapConstantRollupDataToNoir(inputs.constants), - fee_payer_fee_juice_balance_read_hint: mapPublicDataHintToNoir(inputs.feePayerFeeJuiceBalanceReadHint), + archive_root_membership_witness: mapMembershipWitnessToNoir(inputs.hints.archiveRootMembershipWitness), + constants: mapConstantRollupDataToNoir(inputs.hints.constants), + fee_payer_fee_juice_balance_read_hint: mapPublicDataHintToNoir(inputs.hints.feePayerFeeJuiceBalanceReadHint), }; } diff --git a/yarn-project/noir-protocol-circuits-types/src/vks.ts b/yarn-project/noir-protocol-circuits-types/src/vks.ts index bd8e0dbbf4ca..ca1675d32ad8 100644 --- a/yarn-project/noir-protocol-circuits-types/src/vks.ts +++ b/yarn-project/noir-protocol-circuits-types/src/vks.ts @@ -1,6 +1,5 @@ import { BASE_PARITY_INDEX, - BASE_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, BLOCK_ROOT_ROLLUP_INDEX, @@ -9,17 +8,16 @@ import { MERGE_ROLLUP_INDEX, type MerkleTree, MerkleTreeCalculator, + PRIVATE_BASE_ROLLUP_VK_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - PUBLIC_KERNEL_INNER_INDEX, - PUBLIC_KERNEL_MERGE_INDEX, - PUBLIC_KERNEL_TAIL_INDEX, + PUBLIC_BASE_ROLLUP_VK_INDEX, ROOT_PARITY_INDEX, ROOT_ROLLUP_INDEX, - TUBE_INDEX, + TUBE_VK_INDEX, VK_TREE_HEIGHT, VerificationKeyAsFields, VerificationKeyData, @@ -35,10 +33,8 @@ import PrivateKernelInitVkJson from '../artifacts/keys/private_kernel_init.vk.da import PrivateKernelInnerVkJson from '../artifacts/keys/private_kernel_inner.vk.data.json' assert { type: 'json' }; import PrivateKernelTailVkJson from '../artifacts/keys/private_kernel_tail.vk.data.json' assert { type: 'json' }; import PrivateKernelTailToPublicVkJson from '../artifacts/keys/private_kernel_tail_to_public.vk.data.json' assert { type: 'json' }; -import PublicKernelInnerVkJson from '../artifacts/keys/public_kernel_inner.vk.data.json' assert { type: 'json' }; -import PublicKernelMergeVkJson from '../artifacts/keys/public_kernel_merge.vk.data.json' assert { type: 'json' }; -import PublicKernelTailVkJson from '../artifacts/keys/public_kernel_tail.vk.data.json' assert { type: 'json' }; -import BaseRollupVkJson from '../artifacts/keys/rollup_base.vk.data.json' assert { type: 'json' }; +import PrivateBaseRollupVkJson from '../artifacts/keys/rollup_base_private.vk.data.json' assert { type: 'json' }; +import PublicBaseRollupVkJson from '../artifacts/keys/rollup_base_public.vk.data.json' assert { type: 'json' }; import BlockMergeRollupVkJson from '../artifacts/keys/rollup_block_merge.vk.data.json' assert { type: 'json' }; import BlockRootRollupVkJson from '../artifacts/keys/rollup_block_root.vk.data.json' assert { type: 'json' }; import EmptyBlockRootRollupVkJson from '../artifacts/keys/rollup_block_root_empty.vk.data.json' assert { type: 'json' }; @@ -55,12 +51,10 @@ export const TubeVk = keyJsonToVKData(TubeVkJson); export const ServerCircuitVks: Record = { EmptyNestedArtifact: keyJsonToVKData(EmptyNestedVkJson), PrivateKernelEmptyArtifact: keyJsonToVKData(PrivateKernelEmptyVkJson), - PublicKernelInnerArtifact: keyJsonToVKData(PublicKernelInnerVkJson), - PublicKernelMergeArtifact: keyJsonToVKData(PublicKernelMergeVkJson), - PublicKernelTailArtifact: keyJsonToVKData(PublicKernelTailVkJson), BaseParityArtifact: keyJsonToVKData(BaseParityVkJson), RootParityArtifact: keyJsonToVKData(RootParityVkJson), - BaseRollupArtifact: keyJsonToVKData(BaseRollupVkJson), + PrivateBaseRollupArtifact: keyJsonToVKData(PrivateBaseRollupVkJson), + PublicBaseRollupArtifact: keyJsonToVKData(PublicBaseRollupVkJson), MergeRollupArtifact: keyJsonToVKData(MergeRollupVkJson), BlockRootRollupArtifact: keyJsonToVKData(BlockRootRollupVkJson), EmptyBlockRootRollupArtifact: keyJsonToVKData(EmptyBlockRootRollupVkJson), @@ -88,12 +82,10 @@ export const ProtocolCircuitVkIndexes: Record = { PrivateKernelInnerArtifact: PRIVATE_KERNEL_INNER_INDEX, PrivateKernelTailArtifact: PRIVATE_KERNEL_TAIL_INDEX, PrivateKernelTailToPublicArtifact: PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - PublicKernelInnerArtifact: PUBLIC_KERNEL_INNER_INDEX, - PublicKernelMergeArtifact: PUBLIC_KERNEL_MERGE_INDEX, - PublicKernelTailArtifact: PUBLIC_KERNEL_TAIL_INDEX, BaseParityArtifact: BASE_PARITY_INDEX, RootParityArtifact: ROOT_PARITY_INDEX, - BaseRollupArtifact: BASE_ROLLUP_INDEX, + PrivateBaseRollupArtifact: PRIVATE_BASE_ROLLUP_VK_INDEX, + PublicBaseRollupArtifact: PUBLIC_BASE_ROLLUP_VK_INDEX, MergeRollupArtifact: MERGE_ROLLUP_INDEX, BlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_INDEX, BlockMergeRollupArtifact: BLOCK_MERGE_ROLLUP_INDEX, @@ -113,7 +105,7 @@ function buildVKTree() { vkHashes[index] = value.keyAsFields.hash.toBuffer(); } - vkHashes[TUBE_INDEX] = TubeVk.keyAsFields.hash.toBuffer(); + vkHashes[TUBE_VK_INDEX] = TubeVk.keyAsFields.hash.toBuffer(); return calculator.computeTree(vkHashes); } diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index 5d9893c8a8d5..b0d658b5e8db 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -10,7 +10,7 @@ import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, type BaseOrMergeRollupPublicInputs, - BaseRollupInputs, + BaseRollupHints, BlockMergeRollupInputs, type BlockRootOrBlockMergePublicInputs, ConstantRollupData, @@ -18,7 +18,6 @@ import { Fr, type GlobalVariables, Header, - KernelData, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, @@ -43,14 +42,12 @@ import { PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, - type RECURSIVE_PROOF_LENGTH, type RecursiveProof, RootRollupInputs, StateDiffHints, StateReference, VK_TREE_HEIGHT, type VerificationKeyAsFields, - type VerificationKeyData, } from '@aztec/circuits.js'; import { assertPermutation, makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -74,13 +71,11 @@ type BaseTreeNames = 'NoteHashTree' | 'ContractTree' | 'NullifierTree' | 'Public */ export type TreeNames = BaseTreeNames | 'L1ToL2MessageTree' | 'Archive'; -// Builds the base rollup inputs, updating the contract, nullifier, and data trees in the process -export async function buildBaseRollupInput( +// Builds the hints for base rollup. Updating the contract, nullifier, and data trees in the process. +export async function buildBaseRollupHints( tx: ProcessedTx, - proof: RecursiveProof, globalVariables: GlobalVariables, db: MerkleTreeWriteOperations, - kernelVk: VerificationKeyData, ) { // Get trees info before any changes hit const constants = await getConstantRollupData(globalVariables, db); @@ -175,8 +170,7 @@ export async function buildBaseRollupInput( db, ); - return BaseRollupInputs.from({ - kernelData: getKernelDataFor(tx, kernelVk, proof), + return BaseRollupHints.from({ start, stateDiffHints, feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint, @@ -184,9 +178,7 @@ export async function buildBaseRollupInput( sortedPublicDataWritesIndexes: txPublicDataUpdateRequestInfo.sortedPublicDataWritesIndexes, lowPublicDataWritesPreimages: txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages, lowPublicDataWritesMembershipWitnesses: txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses, - archiveRootMembershipWitness, - constants, }); } @@ -398,23 +390,6 @@ export async function getTreeSnapshot(id: MerkleTreeId, db: MerkleTreeReadOperat return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size)); } -export function getKernelDataFor( - tx: ProcessedTx, - vk: VerificationKeyData, - proof: RecursiveProof, -): KernelData { - const leafIndex = getVKIndex(vk); - - return new KernelData( - tx.data, - proof, - // VK for the kernel circuit - vk, - leafIndex, - getVKSiblingPath(leafIndex), - ); -} - export function makeEmptyMembershipWitness(height: N) { return new MembershipWitness( height, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index bf453c98d0ba..67bbf75b88d6 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -1,54 +1,41 @@ import { Body, - EncryptedNoteTxL2Logs, - EncryptedTxL2Logs, L2Block, MerkleTreeId, type PaddingProcessedTx, type ProcessedTx, - ProvingRequestType, - type PublicInputsAndRecursiveProof, type ServerCircuitProver, type TxEffect, - UnencryptedTxL2Logs, makeEmptyProcessedTx, makePaddingProcessedTx, - mapProvingRequestTypeToCircuitName, toTxEffect, } from '@aztec/circuit-types'; import { type EpochProver, type MerkleTreeWriteOperations } from '@aztec/circuit-types/interfaces'; import { type CircuitName } from '@aztec/circuit-types/stats'; import { - AvmCircuitInputs, + AVM_PROOF_LENGTH_IN_FIELDS, + AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, type BaseOrMergeRollupPublicInputs, BaseParityInputs, - type BaseRollupInputs, + type BaseRollupHints, type BlockRootOrBlockMergePublicInputs, BlockRootRollupInputs, EmptyBlockRootRollupInputs, Fr, type GlobalVariables, type Header, - type KernelCircuitPublicInputs, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, - NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_PROOF_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY, PrivateKernelEmptyInputData, - type Proof, - type PublicKernelCircuitPublicInputs, type RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootParityInput, RootParityInputs, - TUBE_INDEX, - type TUBE_PROOF_LENGTH, - TubeInputs, - type VMCircuitPublicInputs, type VerificationKeyAsFields, VerificationKeyData, - makeEmptyProof, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; @@ -59,14 +46,14 @@ import { promiseWithResolvers } from '@aztec/foundation/promise'; import { type Tuple } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; import { elapsed } from '@aztec/foundation/timer'; -import { TubeVk, getVKIndex, getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { Attributes, type TelemetryClient, type Tracer, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client'; import { inspect } from 'util'; import { - buildBaseRollupInput, + buildBaseRollupHints, buildHeaderFromCircuitOutputs, buildHeaderFromTxEffects, createBlockMergeRollupInputs, @@ -87,7 +74,7 @@ import { type TreeSnapshots, } from './epoch-proving-state.js'; import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js'; -import { TX_PROVING_CODE, type TxProvingInstruction, TxProvingState } from './tx-proving-state.js'; +import { TxProvingState } from './tx-proving-state.js'; const logger = createDebugLogger('aztec:prover:proving-orchestrator'); @@ -278,8 +265,8 @@ export class ProvingOrchestrator implements EpochProver { return; } - const [inputs, treeSnapshots] = await this.prepareTransaction(tx, provingState); - this.enqueueFirstProofs(inputs, treeSnapshots, tx, provingState); + const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState); + this.enqueueFirstProofs(hints, treeSnapshots, tx, provingState); if (provingState.transactionsReceived === provingState.totalNumTxs) { logger.verbose(`All transactions received for block ${provingState.globalVariables.blockNumber}.`); @@ -333,11 +320,11 @@ export class ProvingOrchestrator implements EpochProver { getVKTreeRoot(), protocolContractTreeRoot, ); - const txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }> = []; + const txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }> = []; for (let i = 0; i < paddingTxCount; i++) { - const [inputs, snapshot] = await this.prepareTransaction(unprovenPaddingTx, provingState); + const [hints, snapshot] = await this.prepareTransaction(unprovenPaddingTx, provingState); const txInput = { - inputs, + hints, snapshot, }; txInputs.push(txInput); @@ -471,7 +458,7 @@ export class ProvingOrchestrator implements EpochProver { // If the fully proven padding transaction is not available, this will first be proven private enqueuePaddingTxs( provingState: BlockProvingState, - txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }>, + txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }>, unprovenPaddingTx: ProcessedTx, ) { if (this.paddingTx) { @@ -521,21 +508,18 @@ export class ProvingOrchestrator implements EpochProver { * @param provingState - The block proving state */ private provePaddingTransactions( - txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }>, + txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }>, paddingTx: PaddingProcessedTx, provingState: BlockProvingState, ) { // The padding tx contains the proof and vk, generated separately from the base inputs // Copy these into the base rollup inputs and enqueue the base rollup proof for (let i = 0; i < txInputs.length; i++) { - txInputs[i].inputs.kernelData.vk = paddingTx.verificationKey; - txInputs[i].inputs.kernelData.proof = paddingTx.recursiveProof; - - txInputs[i].inputs.kernelData.vkIndex = getVKIndex(paddingTx.verificationKey); - txInputs[i].inputs.kernelData.vkPath = getVKSiblingPath(txInputs[i].inputs.kernelData.vkIndex); - const txProvingState = new TxProvingState(paddingTx, txInputs[i].inputs, txInputs[i].snapshot); + const { hints, snapshot } = txInputs[i]; + const txProvingState = new TxProvingState(paddingTx, hints, snapshot); + txProvingState.assignTubeProof({ proof: paddingTx.recursiveProof, verificationKey: paddingTx.verificationKey }); const txIndex = provingState.addNewTx(txProvingState); - this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState); + this.enqueueBaseRollup(provingState, txIndex); } } @@ -615,20 +599,24 @@ export class ProvingOrchestrator implements EpochProver { } private enqueueFirstProofs( - inputs: BaseRollupInputs, + hints: BaseRollupHints, treeSnapshots: TreeSnapshots, tx: ProcessedTx, provingState: BlockProvingState, ) { - const txProvingState = new TxProvingState(tx, inputs, treeSnapshots); + const txProvingState = new TxProvingState(tx, hints, treeSnapshots); + + const rejectReason = txProvingState.verifyStateOrReject(); + if (rejectReason) { + provingState.reject(rejectReason); + return; + } + const txIndex = provingState.addNewTx(txProvingState); this.enqueueTube(provingState, txIndex); - const numPublicKernels = txProvingState.getNumPublicKernels(); - // Enqueue all of the VM proving requests - // Rather than handle the Kernel Tail as a special case here, we will just handle it inside enqueueVM - for (let i = 0; i < numPublicKernels; i++) { - logger.debug(`Enqueueing public VM ${i} for tx ${txIndex}`); - this.enqueueVM(provingState, txIndex, i); + if (txProvingState.requireAvmProof) { + logger.debug(`Enqueueing public VM for tx ${txIndex}`); + this.enqueueVM(provingState, txIndex); } } @@ -701,7 +689,7 @@ export class ProvingOrchestrator implements EpochProver { private async prepareBaseRollupInputs( provingState: BlockProvingState | undefined, tx: ProcessedTx, - ): Promise<[BaseRollupInputs, TreeSnapshots] | undefined> { + ): Promise<[BaseRollupHints, TreeSnapshots] | undefined> { if (!provingState?.verifyState()) { logger.debug('Not preparing base rollup inputs, state invalid'); return; @@ -709,15 +697,7 @@ export class ProvingOrchestrator implements EpochProver { // We build the base rollup inputs using a mock proof and verification key. // These will be overwritten later once we have proven the tube circuit and any public kernels - const [ms, inputs] = await elapsed( - buildBaseRollupInput( - tx, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - provingState.globalVariables, - this.db, - TubeVk, - ), - ); + const [ms, hints] = await elapsed(buildBaseRollupHints(tx, provingState.globalVariables, this.db)); if (!tx.isEmpty) { this.metrics.recordBaseRollupInputs(ms); @@ -734,81 +714,54 @@ export class ProvingOrchestrator implements EpochProver { logger.debug(`Discarding proving job, state no longer valid`); return; } - return [inputs, treeSnapshots]; + return [hints, treeSnapshots]; } // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit // Executes the next level of merge if all inputs are available - private enqueueBaseRollup(provingState: BlockProvingState | undefined, index: bigint, tx: TxProvingState) { + private enqueueBaseRollup(provingState: BlockProvingState | undefined, txIndex: number) { if (!provingState?.verifyState()) { logger.debug('Not running base rollup, state invalid'); return; } - const txNoteEncryptedLogs = EncryptedNoteTxL2Logs.hashNoteLogs( - tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHashes - .filter(log => !log.isEmpty()) - .map(log => log.value.toBuffer()), - ); - if (!txNoteEncryptedLogs.equals(tx.processedTx.noteEncryptedLogs.hash())) { - provingState.reject( - `Note encrypted logs hash mismatch: ${Fr.fromBuffer(txNoteEncryptedLogs)} === ${Fr.fromBuffer( - tx.processedTx.noteEncryptedLogs.hash(), - )}`, - ); - return; - } - const txEncryptedLogs = EncryptedTxL2Logs.hashSiloedLogs( - tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHashes - .filter(log => !log.isEmpty()) - .map(log => log.getSiloedHash()), - ); - if (!txEncryptedLogs.equals(tx.processedTx.encryptedLogs.hash())) { - // @todo This rejection messages is never seen. Never making it out to the logs - provingState.reject( - `Encrypted logs hash mismatch: ${Fr.fromBuffer(txEncryptedLogs)} === ${Fr.fromBuffer( - tx.processedTx.encryptedLogs.hash(), - )}`, - ); - return; - } - const txUnencryptedLogs = UnencryptedTxL2Logs.hashSiloedLogs( - tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHashes - .filter(log => !log.isEmpty()) - .map(log => log.getSiloedHash()), - ); - if (!txUnencryptedLogs.equals(tx.processedTx.unencryptedLogs.hash())) { - provingState.reject( - `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogs)} === ${Fr.fromBuffer( - tx.processedTx.unencryptedLogs.hash(), - )}`, - ); - return; - } + const txProvingState = provingState.getTxProvingState(txIndex); + const { processedTx } = txProvingState; + const rollupType = txProvingState.requireAvmProof ? 'public-base-rollup' : 'private-base-rollup'; logger.debug( `Enqueuing deferred proving base rollup${ - tx.processedTx.isEmpty ? ' with padding tx' : '' - } for ${tx.processedTx.hash.toString()}`, + processedTx.isEmpty ? ' with padding tx' : '' + } for ${processedTx.hash.toString()}`, ); this.deferredProving( provingState, wrapCallbackInSpan( this.tracer, - 'ProvingOrchestrator.prover.getBaseRollupProof', + `ProvingOrchestrator.prover.${ + rollupType === 'private-base-rollup' ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof' + }`, { - [Attributes.TX_HASH]: tx.processedTx.hash.toString(), + [Attributes.TX_HASH]: processedTx.hash.toString(), [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', - [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup' satisfies CircuitName, + [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType satisfies CircuitName, + }, + signal => { + if (rollupType === 'private-base-rollup') { + const inputs = txProvingState.getPrivateBaseInputs(); + return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber); + } else { + const inputs = txProvingState.getPublicBaseInputs(); + return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber); + } }, - signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal, provingState.epochNumber), ), result => { - logger.debug(`Completed proof for base rollup for tx ${tx.processedTx.hash.toString()}`); - validatePartialState(result.inputs.end, tx.treeSnapshots); + logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`); + validatePartialState(result.inputs.end, txProvingState.treeSnapshots); const currentLevel = provingState.numMergeLevels + 1n; - this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [ + this.storeAndExecuteNextMergeLevel(provingState, currentLevel, BigInt(txIndex), [ result.inputs, result.proof, result.verificationKey.keyAsFields, @@ -838,23 +791,15 @@ export class ProvingOrchestrator implements EpochProver { [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', [Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit' satisfies CircuitName, }, - signal => - this.prover.getTubeProof( - new TubeInputs(txProvingState.processedTx.clientIvcProof), - signal, - provingState.epochNumber, - ), + signal => { + const inputs = txProvingState.getTubeInputs(); + return this.prover.getTubeProof(inputs, signal, provingState.epochNumber); + }, ), result => { logger.debug(`Completed tube proof for tx index: ${txIndex}`); - const nextKernelRequest = txProvingState.getNextPublicKernelFromTubeProof(result.proof, result.verificationKey); - this.checkAndEnqueueNextTxCircuit( - provingState, - txIndex, - result.proof, - result.verificationKey, - nextKernelRequest, - ); + txProvingState.assignTubeProof(result); + this.checkAndEnqueueNextTxCircuit(provingState, txIndex); }, ); } @@ -1199,181 +1144,59 @@ export class ProvingOrchestrator implements EpochProver { * previous kernel is ready * @param provingState - The proving state being operated on * @param txIndex - The index of the transaction being proven - * @param functionIndex - The index of the function/kernel being proven */ - private enqueueVM(provingState: BlockProvingState | undefined, txIndex: number, functionIndex: number) { + private enqueueVM(provingState: BlockProvingState | undefined, txIndex: number) { if (!provingState?.verifyState()) { logger.debug(`Not running VM circuit as state is no longer valid`); return; } const txProvingState = provingState.getTxProvingState(txIndex); - const publicFunction = txProvingState.getPublicFunctionState(functionIndex); - // If there is a VM request, we need to prove it. Otherwise, continue with the kernel. - if (publicFunction.vmRequest) { - // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined. - // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit. - const doAvmProving = wrapCallbackInSpan( - this.tracer, - 'ProvingOrchestrator.prover.getAvmProof', - { - [Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(), - [Attributes.APP_CIRCUIT_NAME]: publicFunction.vmRequest!.functionName, - }, - async (signal: AbortSignal) => { - const inputs: AvmCircuitInputs = new AvmCircuitInputs( - publicFunction.vmRequest!.functionName, - publicFunction.vmRequest!.calldata, - publicFunction.vmRequest!.kernelRequest.inputs.publicCall.publicInputs, - publicFunction.vmRequest!.avmHints, - ); - try { - return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber); - } catch (err) { - if (process.env.AVM_PROVING_STRICT) { - throw err; - } else { - logger.warn( - `Error thrown when proving AVM circuit, but AVM_PROVING_STRICT is off, so faking AVM proof and carrying on. Error: ${err}.`, - ); - return { - proof: makeEmptyProof(), - verificationKey: VerificationKeyData.makeFakeHonk(), - }; - } + // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined. + // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit. + const doAvmProving = wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getAvmProof', + { + [Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(), + }, + async (signal: AbortSignal) => { + const inputs = txProvingState.getAvmInputs(); + try { + return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber); + } catch (err) { + if (process.env.AVM_PROVING_STRICT) { + throw err; + } else { + logger.warn( + `Error thrown when proving AVM circuit, but AVM_PROVING_STRICT is off, so faking AVM proof and carrying on. Error: ${err}.`, + ); + return { + proof: makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), + verificationKey: VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS), + }; } - }, - ); - this.deferredProving(provingState, doAvmProving, proofAndVk => { - logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`); - this.checkAndEnqueuePublicKernelFromVMProof(provingState, txIndex, functionIndex, proofAndVk.proof); - }); - } - } + } + }, + ); - private checkAndEnqueuePublicKernelFromVMProof( - provingState: BlockProvingState, - txIndex: number, - functionIndex: number, - vmProof: Proof, - ) { - const txProvingState = provingState.getTxProvingState(txIndex); - const kernelRequest = txProvingState.getNextPublicKernelFromVMProof(functionIndex, vmProof); - if (kernelRequest.code === TX_PROVING_CODE.READY) { - if (kernelRequest.function === undefined) { - // Should not be possible - throw new Error(`Error occurred, public function request undefined after VM proof completed`); - } - logger.debug(`Enqueuing kernel from VM for tx ${txIndex}, function ${functionIndex}`); - this.enqueuePublicKernel(provingState, txIndex, functionIndex); - } + this.deferredProving(provingState, doAvmProving, proofAndVk => { + logger.debug(`Proven VM for tx index: ${txIndex}`); + txProvingState.assignAvmProof(proofAndVk); + this.checkAndEnqueueNextTxCircuit(provingState, txIndex); + }); } - // Takes a proof and verification key, passes it to the proving state before enqueueing the next proof - // This could be either a public kernel or the base rollup - // Alternatively, if we are still waiting on a public VM prof then it will continue waiting - private checkAndEnqueueNextTxCircuit( - provingState: BlockProvingState, - txIndex: number, - proof: RecursiveProof | RecursiveProof, - verificationKey: VerificationKeyData, - nextKernelRequest: TxProvingInstruction, - ) { + private checkAndEnqueueNextTxCircuit(provingState: BlockProvingState, txIndex: number) { const txProvingState = provingState.getTxProvingState(txIndex); - // What's the status of the next kernel? - if (nextKernelRequest.code === TX_PROVING_CODE.NOT_READY) { - // Must be waiting on a VM proof - return; - } - - if (nextKernelRequest.code === TX_PROVING_CODE.COMPLETED) { - // We must have completed all public function proving, we now move to the base rollup - logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`); - // Take the final proof and assign it to the base rollup inputs - txProvingState.baseRollupInputs.kernelData.proof = proof; - txProvingState.baseRollupInputs.kernelData.vk = verificationKey; - try { - txProvingState.baseRollupInputs.kernelData.vkIndex = getVKIndex(verificationKey); - } catch (_ignored) { - // TODO(#7410) The VK for the tube won't be in the tree for now, so we manually set it to the tube vk index - txProvingState.baseRollupInputs.kernelData.vkIndex = TUBE_INDEX; - } - txProvingState.baseRollupInputs.kernelData.vkPath = getVKSiblingPath( - txProvingState.baseRollupInputs.kernelData.vkIndex, - ); - - this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState); + if (!txProvingState.ready()) { return; } - // There must be another kernel ready to be proven - if (nextKernelRequest.function === undefined) { - // Should not be possible - throw new Error(`Error occurred, public function request undefined after kernel proof completed`); - } - this.enqueuePublicKernel(provingState, txIndex, nextKernelRequest.functionIndex!); - } + // We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup. + logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`); - /** - * Executes the kernel circuit for a public function, will enqueue the next kernel circuit if it's VM is already proven - * or the base rollup circuit if there are no more kernels to be proven - * @param provingState - The proving state being operated on - * @param txIndex - The index of the transaction being proven - * @param functionIndex - The index of the function/kernel being proven - */ - private enqueuePublicKernel(provingState: BlockProvingState | undefined, txIndex: number, functionIndex: number) { - if (!provingState?.verifyState()) { - logger.debug(`Not running public kernel circuit as state is no longer valid`); - return; - } - - const txProvingState = provingState.getTxProvingState(txIndex); - const request = txProvingState.getPublicFunctionState(functionIndex).publicKernelRequest; - - this.deferredProving( - provingState, - wrapCallbackInSpan( - this.tracer, - request.type === ProvingRequestType.PUBLIC_KERNEL_TAIL - ? 'ProvingOrchestrator.prover.getPublicTailProof' - : request.type === ProvingRequestType.PUBLIC_KERNEL_MERGE - ? 'ProvingOrchestrator.prover.getPublicKernelMergeProof' - : 'ProvingOrchestrator.prover.getPublicKernelInnerProof', - { - [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', - [Attributes.PROTOCOL_CIRCUIT_NAME]: mapProvingRequestTypeToCircuitName(request.type), - }, - ( - signal, - ): Promise< - PublicInputsAndRecursiveProof< - KernelCircuitPublicInputs | PublicKernelCircuitPublicInputs | VMCircuitPublicInputs - > - > => { - if (request.type === ProvingRequestType.PUBLIC_KERNEL_TAIL) { - return this.prover.getPublicTailProof(request.inputs, signal, provingState.epochNumber); - } else if (request.type === ProvingRequestType.PUBLIC_KERNEL_MERGE) { - return this.prover.getPublicKernelMergeProof(request.inputs, signal, provingState.epochNumber); - } else { - return this.prover.getPublicKernelInnerProof(request.inputs, signal, provingState.epochNumber); - } - }, - ), - result => { - const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof( - functionIndex, - result.proof, - result.verificationKey, - ); - this.checkAndEnqueueNextTxCircuit( - provingState, - txIndex, - result.proof, - result.verificationKey, - nextKernelRequest, - ); - }, - ); + this.enqueueBaseRollup(provingState, txIndex); } } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 13a8b29dc206..8c87642522d4 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -1,5 +1,6 @@ -import { type ServerCircuitProver } from '@aztec/circuit-types'; +import { ProvingRequestType, type ServerCircuitProver } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; +import { makeAvmCircuitInputs } from '@aztec/circuits.js/testing'; import { times } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { WASMSimulator } from '@aztec/simulator'; @@ -34,37 +35,16 @@ describe('prover/orchestrator/failures', () => { orchestrator = new ProvingOrchestrator(context.actualDb, mockProver, new NoopTelemetryClient()); }); - it.each([ - ['Base Rollup Failed', (msg: string) => jest.spyOn(mockProver, 'getBaseRollupProof').mockRejectedValue(msg)], - ['Merge Rollup Failed', (msg: string) => jest.spyOn(mockProver, 'getMergeRollupProof').mockRejectedValue(msg)], - [ - 'Block Root Rollup Failed', - (msg: string) => jest.spyOn(mockProver, 'getBlockRootRollupProof').mockRejectedValue(msg), - ], - [ - 'Block Merge Rollup Failed', - (msg: string) => jest.spyOn(mockProver, 'getBlockMergeRollupProof').mockRejectedValue(msg), - ], - ['Root Rollup Failed', (msg: string) => jest.spyOn(mockProver, 'getRootRollupProof').mockRejectedValue(msg)], - ['Base Parity Failed', (msg: string) => jest.spyOn(mockProver, 'getBaseParityProof').mockRejectedValue(msg)], - ['Root Parity Failed', (msg: string) => jest.spyOn(mockProver, 'getRootParityProof').mockRejectedValue(msg)], - ] as const)('handles a %s error', async (message: string, fn: (msg: string) => void) => { - /** - * NOTE: these tests start a new epoch with N blocks. Each block will have M txs in it. - * Txs are proven in parallel and as soon as one fails (which is what this test is setting up to happen) - * the orchestrator stops accepting txs in a block. - * This means we have to be careful with our assertions as the order in which things happen is non-deterministic. - * We need to expect - * - addTx to fail (because a block's provingState became invalid) - * - addTx to work fine (because we haven't hit the error in the test setup) but the epoch to fail - */ - fn(message); - + const run = async (message: string) => { orchestrator.startNewEpoch(1, 3); // We need at least 3 blocks and 3 txs to ensure all circuits are used for (let i = 0; i < 3; i++) { const txs = times(3, j => makeBloatedProcessedTx(context.actualDb, i * 10 + j + 1)); + txs[1].avmProvingRequest = { + type: ProvingRequestType.PUBLIC_VM, + inputs: makeAvmCircuitInputs(i), + }; const msgs = [new Fr(i + 100)]; // these operations could fail if the target circuit fails before adding all blocks or txs try { @@ -88,6 +68,47 @@ describe('prover/orchestrator/failures', () => { break; } } + }; + + it('succeeds without failed proof', async () => { + await run('successful case'); + await expect(orchestrator.finaliseEpoch()).resolves.not.toThrow(); + }); + + it.each([ + [ + 'Private Base Rollup Failed', + (msg: string) => jest.spyOn(mockProver, 'getPrivateBaseRollupProof').mockRejectedValue(msg), + ], + [ + 'Public Base Rollup Failed', + (msg: string) => jest.spyOn(mockProver, 'getPublicBaseRollupProof').mockRejectedValue(msg), + ], + ['Merge Rollup Failed', (msg: string) => jest.spyOn(mockProver, 'getMergeRollupProof').mockRejectedValue(msg)], + [ + 'Block Root Rollup Failed', + (msg: string) => jest.spyOn(mockProver, 'getBlockRootRollupProof').mockRejectedValue(msg), + ], + [ + 'Block Merge Rollup Failed', + (msg: string) => jest.spyOn(mockProver, 'getBlockMergeRollupProof').mockRejectedValue(msg), + ], + ['Root Rollup Failed', (msg: string) => jest.spyOn(mockProver, 'getRootRollupProof').mockRejectedValue(msg)], + ['Base Parity Failed', (msg: string) => jest.spyOn(mockProver, 'getBaseParityProof').mockRejectedValue(msg)], + ['Root Parity Failed', (msg: string) => jest.spyOn(mockProver, 'getRootParityProof').mockRejectedValue(msg)], + ] as const)('handles a %s error', async (message: string, makeFailedProof: (msg: string) => void) => { + /** + * NOTE: these tests start a new epoch with N blocks. Each block will have M txs in it. + * Txs are proven in parallel and as soon as one fails (which is what this test is setting up to happen) + * the orchestrator stops accepting txs in a block. + * This means we have to be careful with our assertions as the order in which things happen is non-deterministic. + * We need to expect + * - addTx to fail (because a block's provingState became invalid) + * - addTx to work fine (because we haven't hit the error in the test setup) but the epoch to fail + */ + makeFailedProof(message); + + await run(message); await expect(() => orchestrator.finaliseEpoch()).rejects.toThrow(); }); diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index 57d67bfa9fb7..3c681585bfdd 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -1,43 +1,29 @@ import { - AVM_REQUEST, - type AvmProvingRequest, + EncryptedNoteTxL2Logs, + EncryptedTxL2Logs, type MerkleTreeId, type ProcessedTx, - ProvingRequestType, - type PublicKernelRequest, + type ProofAndVerificationKey, + UnencryptedTxL2Logs, } from '@aztec/circuit-types'; import { + type AVM_PROOF_LENGTH_IN_FIELDS, + AVM_VK_INDEX, type AppendOnlyTreeSnapshot, - type BaseRollupInputs, - type NESTED_RECURSIVE_PROOF_LENGTH, - type Proof, - type RECURSIVE_PROOF_LENGTH, + AvmProofData, + type BaseRollupHints, + Fr, + PrivateBaseRollupInputs, + PrivateTubeData, + PublicBaseRollupInputs, type RecursiveProof, - type VerificationKeyData, - makeEmptyProof, + type TUBE_PROOF_LENGTH, + TUBE_VK_INDEX, + TubeInputs, + VMCircuitPublicInputs, + VkWitnessData, } from '@aztec/circuits.js'; - -export enum TX_PROVING_CODE { - NOT_READY, - READY, - COMPLETED, -} - -export type PublicFunction = { - vmRequest: AvmProvingRequest | undefined; - vmProof: Proof | undefined; - previousProofType: ProvingRequestType; - previousKernelProven: boolean; - publicKernelRequest: PublicKernelRequest; -}; - -// Type encapsulating the instruction to the orchestrator as to what -// needs to be proven next -export type TxProvingInstruction = { - code: TX_PROVING_CODE; - function: PublicFunction | undefined; - functionIndex?: number; -}; +import { getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; /** * Helper class to manage the proving cycle of a transaction @@ -45,153 +31,127 @@ export type TxProvingInstruction = { * Also stores the inputs to the base rollup for this transaction and the tree snapshots */ export class TxProvingState { - private publicFunctions: PublicFunction[] = []; + private tube?: ProofAndVerificationKey>; + private avm?: ProofAndVerificationKey>; constructor( public readonly processedTx: ProcessedTx, - public readonly baseRollupInputs: BaseRollupInputs, + private readonly baseRollupHints: BaseRollupHints, public readonly treeSnapshots: Map, - ) { - let previousProofType = ProvingRequestType.TUBE_PROOF; - for (let i = 0; i < processedTx.publicProvingRequests.length; i++) { - const provingRequest = processedTx.publicProvingRequests[i]; - const publicKernelRequest = provingRequest.type === AVM_REQUEST ? provingRequest.kernelRequest : provingRequest; - const vmRequest = provingRequest.type === AVM_REQUEST ? provingRequest : undefined; - // TODO(#7124): Remove this temporary hack. - // There's no previous kernel for the first inner kernel in a chain of AvmProvingRequests. - // Setting its previousKernelProven to be true so that it will be ready once the vm proof is generated. - const previousKernelProven = !!vmRequest && previousProofType !== ProvingRequestType.PUBLIC_KERNEL_INNER; - const vmProof = provingRequest.type === ProvingRequestType.PUBLIC_KERNEL_TAIL ? makeEmptyProof() : undefined; - const publicFunction: PublicFunction = { - vmRequest, - vmProof, - previousProofType, - previousKernelProven, - publicKernelRequest: { - type: publicKernelRequest.type, - // We take a deep copy (clone) of the inputs to be modified here and passed to the prover. - // bb-prover will also modify the inputs by reference. - inputs: publicKernelRequest.inputs.clone(), - } as PublicKernelRequest, - }; - this.publicFunctions.push(publicFunction); - previousProofType = publicKernelRequest.type; - } + ) {} - if (this.publicFunctions.length > 0) { - // The first merge kernel takes the tube proof. - const firstKernelIndex = this.publicFunctions.findIndex( - fn => fn.publicKernelRequest.type === ProvingRequestType.PUBLIC_KERNEL_MERGE, - ); - this.publicFunctions[firstKernelIndex].previousProofType = ProvingRequestType.TUBE_PROOF; - } + get requireAvmProof() { + return !!this.processedTx.avmProvingRequest; } - // Updates the transaction's proving state after completion of a kernel proof - // Returns an instruction as to the next stage of tx proving - public getNextPublicKernelFromKernelProof( - provenIndex: number, - proof: RecursiveProof, - verificationKey: VerificationKeyData, - ): TxProvingInstruction { - const kernelRequest = this.getPublicFunctionState(provenIndex).publicKernelRequest; - const provenIsInner = kernelRequest.type === ProvingRequestType.PUBLIC_KERNEL_INNER; - // If the proven request is not an inner kernel, its next kernel should not be an inner kernel either. - const nextFunctionIndex = provenIsInner - ? provenIndex + 1 - : this.publicFunctions.findIndex( - (fn, i) => i > provenIndex && fn.publicKernelRequest.type !== ProvingRequestType.PUBLIC_KERNEL_INNER, - ); - if (nextFunctionIndex >= this.publicFunctions.length || nextFunctionIndex === -1) { - // The next kernel index is greater than our set of functions, we are done! - return { code: TX_PROVING_CODE.COMPLETED, function: undefined }; - } + public ready() { + return !!this.tube && (!this.requireAvmProof || !!this.avm); + } - // There is more work to do, are we ready? - const nextFunction = this.publicFunctions[nextFunctionIndex]; - - if (provenIsInner && nextFunction.publicKernelRequest.type !== ProvingRequestType.PUBLIC_KERNEL_INNER) { - // TODO(#7124): Remove this temporary hack. - // If the proven request is inner (with vm proof) and the next one is regular kernel, set the vmProof to be - // not undefined. - // This should eventually be a real vm proof of the entire enqueued call. - nextFunction.vmProof = makeEmptyProof(); - } else { - // pass both the proof and verification key forward to the next circuit - nextFunction.publicKernelRequest.inputs.previousKernel.proof = proof; - nextFunction.publicKernelRequest.inputs.previousKernel.vk = verificationKey; - - // We need to update this so the state machine knows this proof is ready - nextFunction.previousKernelProven = true; - nextFunction.previousProofType = kernelRequest.type; - } + public getTubeInputs() { + return new TubeInputs(this.processedTx.clientIvcProof); + } + + public getAvmInputs() { + return this.processedTx.avmProvingRequest!.inputs; + } - if (nextFunction.vmProof === undefined || !nextFunction.previousKernelProven) { - // The VM proof for the next function is not ready - return { code: TX_PROVING_CODE.NOT_READY, function: undefined }; + public getPrivateBaseInputs() { + if (this.requireAvmProof) { + throw new Error('Should create public base rollup for a tx requiring avm proof.'); } + if (!this.tube) { + throw new Error('Tx not ready for proving base rollup.'); + } + + const vkData = this.getTubeVkData(); + const tubeData = new PrivateTubeData(this.processedTx.data, this.tube.proof, vkData); - // The VM proof is ready, we can continue - return { code: TX_PROVING_CODE.READY, function: nextFunction, functionIndex: nextFunctionIndex }; + return new PrivateBaseRollupInputs(tubeData, this.baseRollupHints); } - // Updates the transaction's proving state after completion of a tube proof - // Returns an instruction as to the next stage of tx proving - public getNextPublicKernelFromTubeProof( - proof: RecursiveProof, - verificationKey: VerificationKeyData, - ): TxProvingInstruction { - const nextFunctionIndex = this.publicFunctions.findIndex( - (fn, i) => i > 0 && fn.previousProofType === ProvingRequestType.TUBE_PROOF, - ); - if (nextFunctionIndex === -1) { - // There are no public functions to be processed, we are done! - return { code: TX_PROVING_CODE.COMPLETED, function: undefined }; + public getPublicBaseInputs() { + if (!this.requireAvmProof) { + throw new Error('Should create private base rollup for a tx not requiring avm proof.'); + } + if (!this.tube) { + throw new Error('Tx not ready for proving base rollup: tube proof undefined'); + } + if (!this.avm) { + throw new Error('Tx not ready for proving base rollup: avm proof undefined'); } - // There is more work to do, are we ready? - const nextFunction = this.publicFunctions[nextFunctionIndex]; + // Temporary hack. + // Passing this.processedTx.data to the tube, which is the output of the simulated public_kernel_tail, + // so that the output of the public base will contain all the side effects. + // This should be the output of the private_kernel_tail_to_public when the output of the avm proof is the result of + // simulating the entire public call stack. + const tubeData = new PrivateTubeData(this.processedTx.data, this.tube.proof, this.getTubeVkData()); + + const avmProofData = new AvmProofData( + VMCircuitPublicInputs.empty(), // TODO + this.avm.proof, + this.getAvmVkData(), + ); - // pass both the proof and verification key forward to the next circuit - nextFunction.publicKernelRequest.inputs.previousKernel.proof = proof; - nextFunction.publicKernelRequest.inputs.previousKernel.vk = verificationKey; + return new PublicBaseRollupInputs(tubeData, avmProofData, this.baseRollupHints); + } - // We need to update this so the state machine knows this proof is ready - nextFunction.previousKernelProven = true; - if (nextFunction.vmProof === undefined) { - // The VM proof for the next function is not ready - return { code: TX_PROVING_CODE.NOT_READY, function: undefined }; - } + public assignTubeProof(tubeProofAndVk: ProofAndVerificationKey>) { + this.tube = tubeProofAndVk; + } - // The VM proof is ready, we can continue - return { code: TX_PROVING_CODE.READY, function: nextFunction, functionIndex: nextFunctionIndex }; + public assignAvmProof(avmProofAndVk: ProofAndVerificationKey>) { + this.avm = avmProofAndVk; } - // Updates the transaction's proving state after completion of a VM proof - // Returns an instruction as to the next stage of tx proving - public getNextPublicKernelFromVMProof(provenIndex: number, proof: Proof): TxProvingInstruction { - const provenFunction = this.publicFunctions[provenIndex]; - provenFunction.vmProof = proof; + public verifyStateOrReject(): string | undefined { + const kernelPublicInputs = this.processedTx.data; + + const txNoteEncryptedLogs = EncryptedNoteTxL2Logs.hashNoteLogs( + kernelPublicInputs.end.noteEncryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.value.toBuffer()), + ); + if (!txNoteEncryptedLogs.equals(this.processedTx.noteEncryptedLogs.hash())) { + return `Note encrypted logs hash mismatch: ${Fr.fromBuffer(txNoteEncryptedLogs)} === ${Fr.fromBuffer( + this.processedTx.noteEncryptedLogs.hash(), + )}`; + } - if (!provenFunction.previousKernelProven) { - // The previous kernel is not yet ready - return { code: TX_PROVING_CODE.NOT_READY, function: undefined }; + const txEncryptedLogs = EncryptedTxL2Logs.hashSiloedLogs( + kernelPublicInputs.end.encryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), + ); + if (!txEncryptedLogs.equals(this.processedTx.encryptedLogs.hash())) { + // @todo This rejection messages is never seen. Never making it out to the logs + return `Encrypted logs hash mismatch: ${Fr.fromBuffer(txEncryptedLogs)} === ${Fr.fromBuffer( + this.processedTx.encryptedLogs.hash(), + )}`; + } + + const txUnencryptedLogs = UnencryptedTxL2Logs.hashSiloedLogs( + kernelPublicInputs.end.unencryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), + ); + if (!txUnencryptedLogs.equals(this.processedTx.unencryptedLogs.hash())) { + return `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogs)} === ${Fr.fromBuffer( + this.processedTx.unencryptedLogs.hash(), + )}`; } - // The previous kernel is ready so we can prove this kernel - return { code: TX_PROVING_CODE.READY, function: provenFunction, functionIndex: provenIndex }; } - // Returns the public function state at the given index - // Throws if out of bounds - public getPublicFunctionState(functionIndex: number) { - if (functionIndex < 0 || functionIndex >= this.publicFunctions.length) { - throw new Error(`Requested public function index was out of bounds`); + private getTubeVkData() { + let vkIndex = TUBE_VK_INDEX; + try { + vkIndex = getVKIndex(this.tube!.verificationKey); + } catch (_ignored) { + // TODO(#7410) The VK for the tube won't be in the tree for now, so we manually set it to the tube vk index } - return this.publicFunctions[functionIndex]; + const vkPath = getVKSiblingPath(vkIndex); + + return new VkWitnessData(this.tube!.verificationKey, vkIndex, vkPath); } - // Returns the number of public kernels required by this transaction - public getNumPublicKernels() { - return this.publicFunctions.length; + private getAvmVkData() { + const vkIndex = AVM_VK_INDEX; + const vkPath = getVKSiblingPath(vkIndex); + return new VkWitnessData(this.avm!.verificationKey, AVM_VK_INDEX, vkPath); } } diff --git a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts index 1a2d7fc8691c..74053580723d 100644 --- a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts +++ b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts @@ -3,15 +3,13 @@ import { ClientIvcProof, Fr, PrivateKernelEmptyInputData, TubeInputs } from '@az import { makeAvmCircuitInputs, makeBaseParityInputs, - makeBaseRollupInputs, makeBlockMergeRollupInputs, makeBlockRootRollupInputs, makeEmptyBlockRootRollupInputs, makeHeader, makeMergeRollupInputs, - makePublicKernelCircuitPrivateInputs, - makePublicKernelInnerCircuitPrivateInputs, - makePublicKernelTailCircuitPrivateInputs, + makePrivateBaseRollupInputs, + makePublicBaseRollupInputs, makeRootParityInputs, makeRootRollupInputs, } from '@aztec/circuits.js/testing'; @@ -38,7 +36,8 @@ describe('Prover agent <-> queue integration', () => { const makeInputs: MakeInputs = { getAvmProof: makeAvmCircuitInputs, getBaseParityProof: makeBaseParityInputs, - getBaseRollupProof: makeBaseRollupInputs, + getPrivateBaseRollupProof: makePrivateBaseRollupInputs, + getPublicBaseRollupProof: makePublicBaseRollupInputs, getRootParityProof: makeRootParityInputs, getBlockMergeRollupProof: makeBlockMergeRollupInputs, getEmptyBlockRootRollupProof: makeEmptyBlockRootRollupInputs, @@ -48,9 +47,6 @@ describe('Prover agent <-> queue integration', () => { getEmptyTubeProof: () => new PrivateKernelEmptyInputData(makeHeader(), Fr.random(), Fr.random(), Fr.random(), Fr.random()), getMergeRollupProof: makeMergeRollupInputs, - getPublicKernelInnerProof: makePublicKernelInnerCircuitPrivateInputs, - getPublicKernelMergeProof: makePublicKernelCircuitPrivateInputs, - getPublicTailProof: makePublicKernelTailCircuitPrivateInputs, getRootRollupProof: makeRootRollupInputs, getTubeProof: () => new TubeInputs(ClientIvcProof.empty()), }; diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts index f552880a31ed..ebd86cf4a0c1 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts @@ -9,8 +9,9 @@ import { } from '@aztec/circuits.js'; import { makeBaseParityInputs, - makeBaseRollupInputs, makeParityPublicInputs, + makePrivateBaseRollupInputs, + makePublicBaseRollupInputs, makeRootRollupInputs, } from '@aztec/circuits.js/testing'; import { makeTuple } from '@aztec/foundation/array'; @@ -38,39 +39,39 @@ describe('MemoryProvingQueue', () => { it('returns jobs in order', async () => { void queue.getBaseParityProof(makeBaseParityInputs()); - void queue.getBaseRollupProof(makeBaseRollupInputs()); + void queue.getPrivateBaseRollupProof(makePrivateBaseRollupInputs()); const job1 = await queue.getProvingJob(); expect(job1?.request.type).toEqual(ProvingRequestType.BASE_PARITY); const job2 = await queue.getProvingJob(); - expect(job2?.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); + expect(job2?.request.type).toEqual(ProvingRequestType.PRIVATE_BASE_ROLLUP); }); it('returns jobs ordered by priority', async () => { // We push base rollup proof requests for a first block - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 1); - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 1); + void queue.getPrivateBaseRollupProof(makePrivateBaseRollupInputs(), undefined, 1); + void queue.getPublicBaseRollupProof(makePublicBaseRollupInputs(), undefined, 1); // The agent consumes one of them - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PRIVATE_BASE_ROLLUP); // A new block comes along with its base rollups, and the orchestrator then pushes a root request for the first one - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 2); - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 2); - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 2); - void queue.getBaseRollupProof(makeBaseRollupInputs(), undefined, 2); + void queue.getPublicBaseRollupProof(makePublicBaseRollupInputs(), undefined, 2); + void queue.getPrivateBaseRollupProof(makePrivateBaseRollupInputs(), undefined, 2); + void queue.getPrivateBaseRollupProof(makePrivateBaseRollupInputs(), undefined, 2); + void queue.getPublicBaseRollupProof(makePublicBaseRollupInputs(), undefined, 2); void queue.getRootRollupProof(makeRootRollupInputs(), undefined, 1); // The next jobs for the agent should be the ones from block 1, skipping the ones for block 2 - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PUBLIC_BASE_ROLLUP); expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.ROOT_ROLLUP); // And the base rollups for block 2 should go next - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); - expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PUBLIC_BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PRIVATE_BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PRIVATE_BASE_ROLLUP); + expect((await queue.getProvingJob())!.request.type).toEqual(ProvingRequestType.PUBLIC_BASE_ROLLUP); }); it('returns undefined when no jobs are available', async () => { diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index 536394062e8b..251e9014004a 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -9,10 +9,10 @@ import { type ServerCircuitProver, } from '@aztec/circuit-types'; import type { + AVM_PROOF_LENGTH_IN_FIELDS, AvmCircuitInputs, BaseOrMergeRollupPublicInputs, BaseParityInputs, - BaseRollupInputs, BlockMergeRollupInputs, BlockRootOrBlockMergePublicInputs, BlockRootRollupInputs, @@ -20,12 +20,9 @@ import type { KernelCircuitPublicInputs, MergeRollupInputs, NESTED_RECURSIVE_PROOF_LENGTH, + PrivateBaseRollupInputs, PrivateKernelEmptyInputData, - Proof, - PublicKernelCircuitPrivateInputs, - PublicKernelCircuitPublicInputs, - PublicKernelInnerCircuitPrivateInputs, - PublicKernelTailCircuitPrivateInputs, + PublicBaseRollupInputs, RECURSIVE_PROOF_LENGTH, RecursiveProof, RootParityInput, @@ -33,7 +30,6 @@ import type { RootRollupInputs, RootRollupPublicInputs, TubeInputs, - VMCircuitPublicInputs, } from '@aztec/circuits.js'; import { randomBytes } from '@aztec/foundation/crypto'; import { AbortError, TimeoutError } from '@aztec/foundation/error'; @@ -316,16 +312,20 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource return this.enqueue({ type: ProvingRequestType.ROOT_PARITY, inputs }, signal, epochNumber); } - /** - * Creates a proof for the given input. - * @param input - Input to the circuit. - */ - getBaseRollupProof( - baseRollupInput: BaseRollupInputs, + getPrivateBaseRollupProof( + inputs: PrivateBaseRollupInputs, + signal?: AbortSignal, + epochNumber?: number, + ): Promise> { + return this.enqueue({ type: ProvingRequestType.PRIVATE_BASE_ROLLUP, inputs }, signal, epochNumber); + } + + getPublicBaseRollupProof( + inputs: PublicBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, ): Promise> { - return this.enqueue({ type: ProvingRequestType.BASE_ROLLUP, inputs: baseRollupInput }, signal, epochNumber); + return this.enqueue({ type: ProvingRequestType.PUBLIC_BASE_ROLLUP, inputs }, signal, epochNumber); } /** @@ -384,42 +384,6 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource return this.enqueue({ type: ProvingRequestType.ROOT_ROLLUP, inputs: input }, signal, epochNumber); } - /** - * Create a public kernel inner proof. - * @param kernelRequest - Object containing the details of the proof required - */ - getPublicKernelInnerProof( - inputs: PublicKernelInnerCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise> { - return this.enqueue({ type: ProvingRequestType.PUBLIC_KERNEL_INNER, inputs }, signal, epochNumber); - } - - /** - * Create a public kernel merge proof. - * @param kernelRequest - Object containing the details of the proof required - */ - getPublicKernelMergeProof( - inputs: PublicKernelCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise> { - return this.enqueue({ type: ProvingRequestType.PUBLIC_KERNEL_MERGE, inputs }, signal, epochNumber); - } - - /** - * Create a public kernel tail proof. - * @param kernelRequest - Object containing the details of the proof required - */ - getPublicTailProof( - inputs: PublicKernelTailCircuitPrivateInputs, - signal?: AbortSignal, - epochNumber?: number, - ): Promise> { - return this.enqueue({ type: ProvingRequestType.PUBLIC_KERNEL_TAIL, inputs }, signal, epochNumber); - } - /** * Creates an AVM proof. */ @@ -427,7 +391,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise>> { return this.enqueue({ type: ProvingRequestType.PUBLIC_VM, inputs }, signal, epochNumber); } diff --git a/yarn-project/prover-client/src/prover-agent/prover-agent.ts b/yarn-project/prover-client/src/prover-agent/prover-agent.ts index 61b3172d548f..9612830020c4 100644 --- a/yarn-project/prover-client/src/prover-agent/prover-agent.ts +++ b/yarn-project/prover-client/src/prover-agent/prover-agent.ts @@ -161,20 +161,12 @@ export class ProverAgent { return this.circuitProver.getAvmProof(inputs); } - case ProvingRequestType.PUBLIC_KERNEL_INNER: { - return this.circuitProver.getPublicKernelInnerProof(inputs); + case ProvingRequestType.PRIVATE_BASE_ROLLUP: { + return this.circuitProver.getPrivateBaseRollupProof(inputs); } - case ProvingRequestType.PUBLIC_KERNEL_MERGE: { - return this.circuitProver.getPublicKernelMergeProof(inputs); - } - - case ProvingRequestType.PUBLIC_KERNEL_TAIL: { - return this.circuitProver.getPublicTailProof(inputs); - } - - case ProvingRequestType.BASE_ROLLUP: { - return this.circuitProver.getBaseRollupProof(inputs); + case ProvingRequestType.PUBLIC_BASE_ROLLUP: { + return this.circuitProver.getPublicBaseRollupProof(inputs); } case ProvingRequestType.MERGE_ROLLUP: { diff --git a/yarn-project/prover-client/src/prover-agent/rpc.ts b/yarn-project/prover-client/src/prover-agent/rpc.ts index b2925276b4e6..ff2a003db2a9 100644 --- a/yarn-project/prover-client/src/prover-agent/rpc.ts +++ b/yarn-project/prover-client/src/prover-agent/rpc.ts @@ -4,7 +4,6 @@ import { AztecAddress, BaseOrMergeRollupPublicInputs, BaseParityInputs, - BaseRollupInputs, BlockMergeRollupInputs, BlockRootOrBlockMergePublicInputs, BlockRootRollupInputs, @@ -15,12 +14,11 @@ import { KernelCircuitPublicInputs, MergeRollupInputs, ParityPublicInputs, + PrivateBaseRollupInputs, PrivateKernelEmptyInputData, Proof, - PublicKernelCircuitPrivateInputs, + PublicBaseRollupInputs, PublicKernelCircuitPublicInputs, - PublicKernelInnerCircuitPrivateInputs, - PublicKernelTailCircuitPrivateInputs, RecursiveProof, RootParityInput, RootParityInputs, @@ -43,7 +41,8 @@ export function createProvingJobSourceServer(queue: ProvingJobSource): JsonRpcSe AvmCircuitInputs, BaseOrMergeRollupPublicInputs, BaseParityInputs, - BaseRollupInputs, + PrivateBaseRollupInputs, + PublicBaseRollupInputs, Fr, Header, KernelCircuitPublicInputs, @@ -53,10 +52,7 @@ export function createProvingJobSourceServer(queue: ProvingJobSource): JsonRpcSe ProvingError, PrivateKernelEmptyInputData, VMCircuitPublicInputs, - PublicKernelInnerCircuitPrivateInputs, - PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs, - PublicKernelTailCircuitPrivateInputs, RecursiveProof, RootParityInput, RootParityInputs, @@ -84,7 +80,8 @@ export function createProvingJobSourceClient( AvmCircuitInputs, BaseOrMergeRollupPublicInputs, BaseParityInputs, - BaseRollupInputs, + PrivateBaseRollupInputs, + PublicBaseRollupInputs, Fr, Header, KernelCircuitPublicInputs, @@ -94,10 +91,7 @@ export function createProvingJobSourceClient( ProvingError, PrivateKernelEmptyInputData, VMCircuitPublicInputs, - PublicKernelInnerCircuitPrivateInputs, - PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs, - PublicKernelTailCircuitPrivateInputs, RecursiveProof, RootParityInput, RootParityInputs, diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index a0fa076e030e..d8ba95940ee8 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -2,16 +2,20 @@ import { BBNativeRollupProver, type BBProverConfig } from '@aztec/bb-prover'; import { makePaddingProcessedTxFromTubeProof } from '@aztec/circuit-types'; import { NESTED_RECURSIVE_PROOF_LENGTH, + PRIVATE_KERNEL_EMPTY_INDEX, + PrivateBaseRollupInputs, PrivateKernelEmptyInputData, + PrivateTubeData, + VkWitnessData, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; -import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { TestContext } from '../mocks/test_context.js'; -import { buildBaseRollupInput } from '../orchestrator/block-building-helpers.js'; +import { buildBaseRollupHints } from '../orchestrator/block-building-helpers.js'; const logger = createDebugLogger('aztec:bb-prover-base-rollup'); @@ -43,19 +47,25 @@ describe('prover/bb_prover/base-rollup', () => { logger.verbose('Building base rollup inputs'); const baseRollupInputProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - baseRollupInputProof.proof[0] = paddingTxPublicInputsAndProof.verificationKey.keyAsFields.key[0]; - baseRollupInputProof.proof[1] = paddingTxPublicInputsAndProof.verificationKey.keyAsFields.key[1]; - baseRollupInputProof.proof[2] = paddingTxPublicInputsAndProof.verificationKey.keyAsFields.key[2]; - const baseRollupInputs = await buildBaseRollupInput( - tx, - baseRollupInputProof, - context.globalVariables, - context.actualDb, - paddingTxPublicInputsAndProof.verificationKey, - ); + const verificationKey = paddingTxPublicInputsAndProof.verificationKey; + baseRollupInputProof.proof[0] = verificationKey.keyAsFields.key[0]; + baseRollupInputProof.proof[1] = verificationKey.keyAsFields.key[1]; + baseRollupInputProof.proof[2] = verificationKey.keyAsFields.key[2]; + + const vkIndex = PRIVATE_KERNEL_EMPTY_INDEX; + const vkPath = getVKSiblingPath(vkIndex); + const vkData = new VkWitnessData(verificationKey, vkIndex, vkPath); + + const tubeData = new PrivateTubeData(tx.data, baseRollupInputProof, vkData); + + const baseRollupHints = await buildBaseRollupHints(tx, context.globalVariables, context.actualDb); + const baseRollupInputs = new PrivateBaseRollupInputs(tubeData, baseRollupHints); + logger.verbose('Proving base rollups'); - const proofOutputs = await context.prover.getBaseRollupProof(baseRollupInputs); + const proofOutputs = await context.prover.getPrivateBaseRollupProof(baseRollupInputs); logger.verbose('Verifying base rollups'); - await expect(prover.verifyProof('BaseRollupArtifact', proofOutputs.proof.binaryProof)).resolves.not.toThrow(); + await expect( + prover.verifyProof('PrivateBaseRollupArtifact', proofOutputs.proof.binaryProof), + ).resolves.not.toThrow(); }); }); diff --git a/yarn-project/prover-client/src/test/mock_prover.ts b/yarn-project/prover-client/src/test/mock_prover.ts index 1e53e562507c..212c8b549fd8 100644 --- a/yarn-project/prover-client/src/test/mock_prover.ts +++ b/yarn-project/prover-client/src/test/mock_prover.ts @@ -6,28 +6,25 @@ import { makePublicInputsAndRecursiveProof, } from '@aztec/circuit-types'; import { + AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, type BaseOrMergeRollupPublicInputs, type BlockRootOrBlockMergePublicInputs, type KernelCircuitPublicInputs, - type PublicKernelCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootRollupPublicInputs, TUBE_PROOF_LENGTH, - type VMCircuitPublicInputs, VerificationKeyData, - makeEmptyProof, + makeEmptyRecursiveProof, makeRecursiveProof, } from '@aztec/circuits.js'; import { makeBaseOrMergeRollupPublicInputs, makeBlockRootOrBlockMergeRollupPublicInputs, makeKernelCircuitPublicInputs, - makePublicKernelCircuitPublicInputs, makeRootParityInput, makeRootRollupPublicInputs, - makeVMCircuitPublicInputs, } from '@aztec/circuits.js/testing'; export class MockProver implements ServerCircuitProver { @@ -36,7 +33,7 @@ export class MockProver implements ServerCircuitProver { getAvmProof() { return Promise.resolve( makeProofAndVerificationKey( - makeEmptyProof(), + makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS), ), ); @@ -50,7 +47,7 @@ export class MockProver implements ServerCircuitProver { return Promise.resolve(makeRootParityInput(RECURSIVE_PROOF_LENGTH)); } - getBaseRollupProof() { + getPrivateBaseRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBaseOrMergeRollupPublicInputs(), @@ -60,7 +57,7 @@ export class MockProver implements ServerCircuitProver { ); } - getMergeRollupProof(): Promise> { + getPublicBaseRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBaseOrMergeRollupPublicInputs(), @@ -70,17 +67,17 @@ export class MockProver implements ServerCircuitProver { ); } - getBlockMergeRollupProof() { + getMergeRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( - makeBlockRootOrBlockMergeRollupPublicInputs(), + makeBaseOrMergeRollupPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk(), ), ); } - getEmptyBlockRootRollupProof(): Promise> { + getBlockMergeRollupProof() { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBlockRootOrBlockMergeRollupPublicInputs(), @@ -90,7 +87,7 @@ export class MockProver implements ServerCircuitProver { ); } - getBlockRootRollupProof(): Promise> { + getEmptyBlockRootRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBlockRootOrBlockMergeRollupPublicInputs(), @@ -100,17 +97,17 @@ export class MockProver implements ServerCircuitProver { ); } - getEmptyPrivateKernelProof(): Promise> { + getBlockRootRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( - makeKernelCircuitPublicInputs(), + makeBlockRootOrBlockMergeRollupPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk(), ), ); } - getEmptyTubeProof(): Promise> { + getEmptyPrivateKernelProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( makeKernelCircuitPublicInputs(), @@ -120,27 +117,7 @@ export class MockProver implements ServerCircuitProver { ); } - getPublicKernelInnerProof(): Promise> { - return Promise.resolve( - makePublicInputsAndRecursiveProof( - makeVMCircuitPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), - ), - ); - } - - getPublicKernelMergeProof(): Promise> { - return Promise.resolve( - makePublicInputsAndRecursiveProof( - makePublicKernelCircuitPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), - ), - ); - } - - getPublicTailProof(): Promise> { + getEmptyTubeProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( makeKernelCircuitPublicInputs(), diff --git a/yarn-project/sequencer-client/src/block_builder/light.test.ts b/yarn-project/sequencer-client/src/block_builder/light.test.ts index 25372470b9cb..b909191f0709 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.test.ts @@ -23,11 +23,15 @@ import { NUM_BASE_PARITY_PER_ROOT_PARITY, type ParityPublicInputs, PreviousRollupData, + PrivateBaseRollupInputs, + PrivateTubeData, type RecursiveProof, RootParityInput, RootParityInputs, + TUBE_VK_INDEX, VK_TREE_HEIGHT, type VerificationKeyAsFields, + VkWitnessData, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { makeGlobalVariables } from '@aztec/circuits.js/testing'; @@ -43,7 +47,7 @@ import { } from '@aztec/noir-protocol-circuits-types'; import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { - buildBaseRollupInput, + buildBaseRollupHints, buildHeaderFromCircuitOutputs, getRootTreeSiblingPath, getSubtreeSiblingPath, @@ -219,7 +223,7 @@ describe('LightBlockBuilder', () => { getTopMerges = rollupOutputs => Promise.resolve([rollupOutputs[0], rollupOutputs[1]]); } - const rollupOutputs = await getRollupOutputs(txs); + const rollupOutputs = await getPrivateBaseRollupOutputs(txs); const [mergeLeft, mergeRight] = await getTopMerges!(rollupOutputs); const l1ToL2Snapshot = await getL1ToL2Snapshot(l1ToL2Messages); const parityOutput = await getParityOutput(l1ToL2Messages); @@ -250,18 +254,23 @@ describe('LightBlockBuilder', () => { return { messageTreeSnapshot, newL1ToL2MessageTreeRootSiblingPath, l1ToL2Messages }; }; - const getRollupOutputs = async (txs: ProcessedTx[]) => { + const getPrivateBaseRollupOutputs = async (txs: ProcessedTx[]) => { const rollupOutputs = []; for (const tx of txs) { - const inputs = await buildBaseRollupInput(tx, emptyProof, globals, expectsFork, TubeVk); - const result = await simulator.getBaseRollupProof(inputs); + const vkIndex = TUBE_VK_INDEX; + const vkPath = getVKSiblingPath(vkIndex); + const vkData = new VkWitnessData(TubeVk, vkIndex, vkPath); + const tubeData = new PrivateTubeData(tx.data, emptyProof, vkData); + const hints = await buildBaseRollupHints(tx, globals, expectsFork); + const inputs = new PrivateBaseRollupInputs(tubeData, hints); + const result = await simulator.getPrivateBaseRollupProof(inputs); rollupOutputs.push(result.inputs); } return rollupOutputs; }; const getMergeOutput = async (left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) => { - const baseRollupVk = ProtocolCircuitVks['BaseRollupArtifact'].keyAsFields; + const baseRollupVk = ProtocolCircuitVks['PrivateBaseRollupArtifact'].keyAsFields; const baseRollupVkWitness = getVkMembershipWitness(baseRollupVk); const leftInput = new PreviousRollupData(left, emptyProof, baseRollupVk, baseRollupVkWitness); const rightInput = new PreviousRollupData(right, emptyProof, baseRollupVk, baseRollupVkWitness); diff --git a/yarn-project/sequencer-client/src/block_builder/light.ts b/yarn-project/sequencer-client/src/block_builder/light.ts index 158f846a62ca..8598fc37ed4f 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.ts @@ -10,17 +10,11 @@ import { makeEmptyProcessedTx, toTxEffect, } from '@aztec/circuit-types'; -import { - Fr, - type GlobalVariables, - NESTED_RECURSIVE_PROOF_LENGTH, - NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, - makeEmptyRecursiveProof, -} from '@aztec/circuits.js'; +import { Fr, type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { TubeVk, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; -import { buildBaseRollupInput, buildHeaderFromTxEffects, getTreeSnapshot } from '@aztec/prover-client/helpers'; +import { buildBaseRollupHints, buildHeaderFromTxEffects, getTreeSnapshot } from '@aztec/prover-client/helpers'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -51,13 +45,7 @@ export class LightweightBlockBuilder implements BlockBuilder { async addNewTx(tx: ProcessedTx): Promise { this.logger.verbose('Adding new tx to block', { txHash: tx.hash.toString() }); this.txs.push(tx); - await buildBaseRollupInput( - tx, - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - this.globalVariables!, - this.db, - TubeVk, - ); + await buildBaseRollupHints(tx, this.globalVariables!, this.db); } async setBlockCompleted(): Promise { diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 02aeb846a8c4..69ae578fea2d 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -142,7 +142,7 @@ describe('sequencer', () => { publicProcessor = mock({ process: async txs => [ - await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), []))), + await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs()))), [], [], ], diff --git a/yarn-project/simulator/src/common/index.ts b/yarn-project/simulator/src/common/index.ts index 9e61c2e99e57..c1da4735a9f0 100644 --- a/yarn-project/simulator/src/common/index.ts +++ b/yarn-project/simulator/src/common/index.ts @@ -1,3 +1,2 @@ export * from './packed_values_cache.js'; export * from './errors.js'; -export * from './side_effect_counter.js'; diff --git a/yarn-project/simulator/src/common/side_effect_counter.ts b/yarn-project/simulator/src/common/side_effect_counter.ts deleted file mode 100644 index afa49fee00fe..000000000000 --- a/yarn-project/simulator/src/common/side_effect_counter.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Keep track of the number of side effects across execution contexts. - */ -export class SideEffectCounter { - constructor(private value = 0) {} - - // TODO(alexg) remove this once public side effect counters is fully accounted for on Noir side - current() { - return this.value; - } - - count() { - const value = this.value; - this.value++; - return value; - } -} diff --git a/yarn-project/simulator/src/public/enqueued_call_simulator.ts b/yarn-project/simulator/src/public/enqueued_call_simulator.ts index 166014d1f8b1..e33679b7e23a 100644 --- a/yarn-project/simulator/src/public/enqueued_call_simulator.ts +++ b/yarn-project/simulator/src/public/enqueued_call_simulator.ts @@ -1,17 +1,16 @@ import { - AVM_REQUEST, type AvmProvingRequest, MerkleTreeId, NestedProcessReturnValues, ProvingRequestType, type PublicExecutionRequest, PublicKernelPhase, - type PublicProvingRequest, type SimulationError, type Tx, UnencryptedFunctionL2Logs, } from '@aztec/circuit-types'; import { + AvmCircuitInputs, AztecAddress, ContractStorageRead, ContractStorageUpdateRequest, @@ -52,6 +51,7 @@ import { RevertCode, TreeLeafReadRequest, VMCircuitPublicInputs, + VerificationKeyData, makeEmptyProof, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; @@ -59,33 +59,22 @@ import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; -import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types'; import { type MerkleTreeReadOperations } from '@aztec/world-state'; import { type PublicExecutionResult, accumulatePublicReturnValues, collectExecutionResults } from './execution.js'; import { type PublicExecutor } from './executor.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; -function makeAvmProvingRequest( - inputs: PublicKernelInnerCircuitPrivateInputs, - result: PublicExecutionResult, -): AvmProvingRequest { +function makeAvmProvingRequest(inputs: PublicCircuitPublicInputs, result: PublicExecutionResult): AvmProvingRequest { return { - type: AVM_REQUEST, - functionName: result.functionName, - calldata: result.calldata, - bytecode: result.bytecode!, - avmHints: result.avmCircuitHints, - kernelRequest: { - type: ProvingRequestType.PUBLIC_KERNEL_INNER, - inputs, - }, + type: ProvingRequestType.PUBLIC_VM, + inputs: new AvmCircuitInputs(result.functionName, result.calldata, inputs, result.avmCircuitHints), }; } export type EnqueuedCallResult = { /** Inputs to be used for proving */ - provingRequests: PublicProvingRequest[]; + avmProvingRequest: AvmProvingRequest; /** The public kernel output at the end of the enqueued call */ kernelOutput: VMCircuitPublicInputs; /** Unencrypted logs generated during the execution of this enqueued call */ @@ -186,7 +175,7 @@ export class EnqueuedCallSimulator { ): Promise { const executionResults = collectExecutionResults(topResult); - const provingRequests: AvmProvingRequest[] = []; + let avmProvingRequest: AvmProvingRequest; let gasUsed = Gas.empty(); let revertReason; let kernelOutput = startVMCircuitOutput; @@ -215,7 +204,7 @@ export class EnqueuedCallSimulator { kernelOutput = output; // Capture the inputs for later proving in the AVM and kernel. - provingRequests.push(makeAvmProvingRequest(inputs, result)); + avmProvingRequest = makeAvmProvingRequest(inputs.publicCall.publicInputs, result); // Safely return the revert reason and the kernel output (which has had its revertible side effects dropped) // TODO(@leila) we shouldn't drop everything when it reverts. The tail kernel needs the data to prove that it's reverted for the correct reason. @@ -226,7 +215,7 @@ export class EnqueuedCallSimulator { // TODO(@spalladino): Check gasUsed is correct. The AVM should take care of setting gasLeft to zero upon a revert. return { - provingRequests, + avmProvingRequest, kernelOutput, newUnencryptedLogs: UnencryptedFunctionL2Logs.empty(), returnValues: NestedProcessReturnValues.empty(), @@ -237,7 +226,7 @@ export class EnqueuedCallSimulator { } return { - provingRequests, + avmProvingRequest: avmProvingRequest!, kernelOutput, newUnencryptedLogs: topResult.allUnencryptedLogs, returnValues: accumulatePublicReturnValues(topResult), @@ -257,7 +246,7 @@ export class EnqueuedCallSimulator { ): Promise<{ inputs: PublicKernelInnerCircuitPrivateInputs; output: VMCircuitPublicInputs }> { // The proof is not used in simulation const proof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - const vk = ProtocolCircuitVks.PublicKernelInnerArtifact; + const vk = VerificationKeyData.makeFakeHonk(); const previousKernel = new PublicKernelInnerData(previousOutput, proof, vk); const inputs = new PublicKernelInnerCircuitPrivateInputs(previousKernel, callData); return { inputs, output: await this.publicKernelSimulator.publicKernelCircuitInner(inputs) }; diff --git a/yarn-project/simulator/src/public/enqueued_calls_processor.ts b/yarn-project/simulator/src/public/enqueued_calls_processor.ts index 5dfbcc5c161f..f76be43b1549 100644 --- a/yarn-project/simulator/src/public/enqueued_calls_processor.ts +++ b/yarn-project/simulator/src/public/enqueued_calls_processor.ts @@ -1,12 +1,10 @@ import { + type AvmProvingRequest, type MerkleTreeReadOperations, type NestedProcessReturnValues, type ProcessedTx, - ProvingRequestType, type PublicExecutionRequest, - type PublicKernelMergeRequest, PublicKernelPhase, - type PublicProvingRequest, type SimulationError, type Tx, } from '@aztec/circuit-types'; @@ -23,12 +21,13 @@ import { type PublicKernelCircuitPublicInputs, PublicKernelData, type VMCircuitPublicInputs, + VerificationKeyData, makeEmptyProof, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; -import { ProtocolCircuitVks, TubeVk, getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; +import { getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; import { inspect } from 'util'; @@ -45,10 +44,9 @@ const PhaseIsRevertible: Record = { }; type PublicPhaseResult = { + avmProvingRequest: AvmProvingRequest; /** The output of the public kernel circuit simulation for this phase */ publicKernelOutput: PublicKernelCircuitPublicInputs; - /** The collection of public proving requests */ - provingRequests: PublicProvingRequest[]; /** Return values of simulating complete callstack */ returnValues: NestedProcessReturnValues[]; /** Gas used during the execution this phase */ @@ -66,8 +64,7 @@ export type ProcessedPhase = { }; export type TxPublicCallsResult = { - /** The collection of public proving requests */ - provingRequests: PublicProvingRequest[]; + avmProvingRequest: AvmProvingRequest; /** The output of the public kernel tail circuit simulation for this tx */ tailKernelOutput: KernelCircuitPublicInputs; /** Return values of simulating complete callstack */ @@ -158,8 +155,8 @@ export class EnqueuedCallsProcessor { PublicKernelPhase.TEARDOWN, ]; const processedPhases: ProcessedPhase[] = []; - const provingRequests: PublicProvingRequest[] = []; const gasUsed: ProcessedTx['gasUsed'] = {}; + let avmProvingRequest: AvmProvingRequest; let publicKernelOutput = tx.data.toPublicKernelCircuitPublicInputs(); let isFromPrivate = true; let returnValues: NestedProcessReturnValues[] = []; @@ -184,7 +181,9 @@ export class EnqueuedCallsProcessor { publicKernelOutput = result.publicKernelOutput; isFromPrivate = false; - provingRequests.push(...result.provingRequests); + // Propagate only one avmProvingRequest of a function call for now, so that we know it's still provable. + // Eventually this will be the proof for the entire public call stack. + avmProvingRequest = result.avmProvingRequest; if (phase === PublicKernelPhase.APP_LOGIC) { returnValues = result.returnValues; } @@ -201,19 +200,16 @@ export class EnqueuedCallsProcessor { } } - const { output: tailKernelOutput, provingRequest } = await this.publicKernelTailSimulator - .simulate(publicKernelOutput) - .catch( - // the abstract phase manager throws if simulation gives error in non-revertible phase - async err => { - await this.worldStateDB.rollbackToCommit(); - throw err; - }, - ); - provingRequests.push(provingRequest); + const tailKernelOutput = await this.publicKernelTailSimulator.simulate(publicKernelOutput).catch( + // the abstract phase manager throws if simulation gives error in non-revertible phase + async err => { + await this.worldStateDB.rollbackToCommit(); + throw err; + }, + ); return { - provingRequests: provingRequests, + avmProvingRequest: avmProvingRequest!, tailKernelOutput, returnValues, gasUsed, @@ -233,8 +229,8 @@ export class EnqueuedCallsProcessor { this.log.debug(`Beginning processing in phase ${PublicKernelPhase[phase]} for tx ${tx.getTxHash()}`); const phaseTimer = new Timer(); - const provingRequests: PublicProvingRequest[] = []; const returnValues: NestedProcessReturnValues[] = []; + let avmProvingRequest: AvmProvingRequest; let publicKernelOutput = previousPublicKernelOutput; let gasUsed = Gas.empty(); let revertReason: SimulationError | undefined; @@ -270,7 +266,7 @@ export class EnqueuedCallsProcessor { throw enqueuedCallResult.revertReason; } - provingRequests.push(...enqueuedCallResult.provingRequests); + avmProvingRequest = enqueuedCallResult.avmProvingRequest; returnValues.push(enqueuedCallResult.returnValues); gasUsed = gasUsed.add(enqueuedCallResult.gasUsed); revertReason ??= enqueuedCallResult.revertReason; @@ -286,14 +282,13 @@ export class EnqueuedCallsProcessor { tx.unencryptedLogs.addFunctionLogs([enqueuedCallResult.newUnencryptedLogs]); } - const { output, provingRequest } = await this.runMergeKernelCircuit( + const output = await this.runMergeKernelCircuit( publicKernelOutput, enqueuedCallResult.kernelOutput, isFromPrivate, ); publicKernelOutput = output; isFromPrivate = false; - provingRequests.push(provingRequest); } if (phase === PublicKernelPhase.SETUP) { @@ -301,8 +296,8 @@ export class EnqueuedCallsProcessor { } return { + avmProvingRequest: avmProvingRequest!, publicKernelOutput, - provingRequests, durationMs: phaseTimer.ms(), gasUsed, returnValues: revertReason ? [] : returnValues, @@ -349,7 +344,7 @@ export class EnqueuedCallsProcessor { previousOutput: PublicKernelCircuitPublicInputs, enqueuedCallData: VMCircuitPublicInputs, isFromPrivate: boolean, - ): Promise<{ output: PublicKernelCircuitPublicInputs; provingRequest: PublicKernelMergeRequest }> { + ): Promise { const previousKernel = this.getPreviousKernelData(previousOutput, isFromPrivate); // The proof is not used in simulation. @@ -358,25 +353,18 @@ export class EnqueuedCallsProcessor { const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData); - const output = await this.publicKernelSimulator.publicKernelCircuitMerge(inputs); - - const provingRequest: PublicKernelMergeRequest = { - type: ProvingRequestType.PUBLIC_KERNEL_MERGE, - inputs, - }; - - return { output, provingRequest }; + return await this.publicKernelSimulator.publicKernelCircuitMerge(inputs); } private getPreviousKernelData( previousOutput: PublicKernelCircuitPublicInputs, - isFromPrivate: boolean, + _isFromPrivate: boolean, ): PublicKernelData { // The proof is not used in simulation. const proof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - const vk = isFromPrivate ? TubeVk : ProtocolCircuitVks.PublicKernelMergeArtifact; - const vkIndex = getVKIndex(vk); + const vk = VerificationKeyData.makeFakeHonk(); + const vkIndex = 0; const siblingPath = getVKSiblingPath(vkIndex); return new PublicKernelData(previousOutput, proof, vk, vkIndex, siblingPath); diff --git a/yarn-project/simulator/src/public/public_kernel.ts b/yarn-project/simulator/src/public/public_kernel.ts index 0ec6c2570863..4a8c9198aa8d 100644 --- a/yarn-project/simulator/src/public/public_kernel.ts +++ b/yarn-project/simulator/src/public/public_kernel.ts @@ -1,4 +1,3 @@ -import { type CircuitSimulationStats } from '@aztec/circuit-types/stats'; import { type KernelCircuitPublicInputs, type PublicKernelCircuitPrivateInputs, @@ -10,7 +9,9 @@ import { import { createDebugLogger } from '@aztec/foundation/log'; import { elapsed } from '@aztec/foundation/timer'; import { - SimulatedServerCircuitArtifacts, + SimulatedPublicKernelInnerArtifact, + SimulatedPublicKernelMergeArtifact, + SimulatedPublicKernelTailArtifact, convertSimulatedPublicInnerInputsToWitnessMap, convertSimulatedPublicInnerOutputFromWitnessMap, convertSimulatedPublicMergeInputsToWitnessMap, @@ -19,7 +20,6 @@ import { convertSimulatedPublicTailOutputFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; -import { WASMSimulator } from '../providers/acvm_wasm.js'; import { type SimulationProvider } from '../providers/simulation_provider.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; @@ -29,9 +29,6 @@ import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simul export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimulator { private log = createDebugLogger('aztec:public-kernel-simulator'); - // Some circuits are so small it is faster to use WASM - private wasmSimulator: WASMSimulator = new WASMSimulator(); - constructor(private simulator: SimulationProvider) {} /** @@ -42,7 +39,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu public async publicKernelCircuitInner(input: PublicKernelInnerCircuitPrivateInputs): Promise { const inputWitness = convertSimulatedPublicInnerInputsToWitnessMap(input); const [duration, witness] = await elapsed(() => - this.wasmSimulator.simulateCircuit(inputWitness, SimulatedServerCircuitArtifacts.PublicKernelInnerArtifact), + this.simulator.simulateCircuit(inputWitness, SimulatedPublicKernelInnerArtifact), ); const result = convertSimulatedPublicInnerOutputFromWitnessMap(witness); this.log.debug(`Simulated public kernel inner circuit`, { @@ -51,7 +48,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu duration, inputSize: input.toBuffer().length, outputSize: result.toBuffer().length, - } satisfies CircuitSimulationStats); + }); return result; } @@ -65,7 +62,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu ): Promise { const inputWitness = convertSimulatedPublicMergeInputsToWitnessMap(input); const [duration, witness] = await elapsed(() => - this.wasmSimulator.simulateCircuit(inputWitness, SimulatedServerCircuitArtifacts.PublicKernelMergeArtifact), + this.simulator.simulateCircuit(inputWitness, SimulatedPublicKernelMergeArtifact), ); const result = convertSimulatedPublicMergeOutputFromWitnessMap(witness); this.log.debug(`Simulated public kernel merge circuit`, { @@ -74,7 +71,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu duration, inputSize: input.toBuffer().length, outputSize: result.toBuffer().length, - } satisfies CircuitSimulationStats); + }); return result; } @@ -88,7 +85,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu ): Promise { const inputWitness = convertSimulatedPublicTailInputsToWitnessMap(input); const [duration, witness] = await elapsed(() => - this.wasmSimulator.simulateCircuit(inputWitness, SimulatedServerCircuitArtifacts.PublicKernelTailArtifact), + this.simulator.simulateCircuit(inputWitness, SimulatedPublicKernelTailArtifact), ); const result = convertSimulatedPublicTailOutputFromWitnessMap(witness); this.log.debug(`Simulated public kernel tail circuit`, { @@ -97,7 +94,7 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu duration, inputSize: input.toBuffer().length, outputSize: result.toBuffer().length, - } satisfies CircuitSimulationStats); + }); return result; } } diff --git a/yarn-project/simulator/src/public/public_kernel_tail_simulator.ts b/yarn-project/simulator/src/public/public_kernel_tail_simulator.ts index 6904332e861a..6143f5b316dc 100644 --- a/yarn-project/simulator/src/public/public_kernel_tail_simulator.ts +++ b/yarn-project/simulator/src/public/public_kernel_tail_simulator.ts @@ -1,4 +1,3 @@ -import { ProvingRequestType, type PublicKernelTailRequest } from '@aztec/circuit-types'; import { type KernelCircuitPublicInputs, MAX_NULLIFIERS_PER_TX, @@ -7,10 +6,11 @@ import { type PublicKernelCircuitPublicInputs, PublicKernelData, PublicKernelTailCircuitPrivateInputs, + VerificationKeyData, makeEmptyRecursiveProof, mergeAccumulatedData, } from '@aztec/circuits.js'; -import { ProtocolCircuitVks, getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; +import { getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; import { type MerkleTreeReadOperations } from '@aztec/world-state'; import { HintsBuilder } from './hints_builder.js'; @@ -28,19 +28,10 @@ export class PublicKernelTailSimulator { return new PublicKernelTailSimulator(db, publicKernelSimulator, hintsBuilder); } - async simulate( - previousOutput: PublicKernelCircuitPublicInputs, - ): Promise<{ output: KernelCircuitPublicInputs; provingRequest: PublicKernelTailRequest }> { + async simulate(previousOutput: PublicKernelCircuitPublicInputs): Promise { const inputs = await this.buildPrivateInputs(previousOutput); - const output = await this.publicKernelSimulator.publicKernelCircuitTail(inputs); - - const provingRequest: PublicKernelTailRequest = { - type: ProvingRequestType.PUBLIC_KERNEL_TAIL, - inputs, - }; - - return { output, provingRequest }; + return await this.publicKernelSimulator.publicKernelCircuitTail(inputs); } private async buildPrivateInputs(previousOutput: PublicKernelCircuitPublicInputs) { @@ -98,8 +89,8 @@ export class PublicKernelTailSimulator { private getPreviousKernelData(previousOutput: PublicKernelCircuitPublicInputs): PublicKernelData { const proof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - const vk = ProtocolCircuitVks.PublicKernelMergeArtifact; - const vkIndex = getVKIndex(vk); + const vk = VerificationKeyData.makeFakeHonk(); + const vkIndex = 0; const siblingPath = getVKSiblingPath(vkIndex); return new PublicKernelData(previousOutput, proof, vk, vkIndex, siblingPath); } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 2d578e20b124..acede1589750 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -108,7 +108,7 @@ describe('public_processor', () => { clientIvcProof: tx.clientIvcProof, isEmpty: false, revertReason: undefined, - publicProvingRequests: [], + avmProvingRequest: undefined, gasUsed: {}, finalPublicDataUpdateRequests: times( MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 1d6523af65ad..3f58c4d43dba 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -152,7 +152,7 @@ export class PublicProcessor { } try { const [processedTx, returnValues] = !tx.hasPublicCalls() - ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), [])] + ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs())] : await this.processTxWithPublicCalls(tx); this.log.debug(`Processed tx`, { txHash: processedTx.hash, @@ -253,7 +253,7 @@ export class PublicProcessor { private async processTxWithPublicCalls(tx: Tx): Promise<[ProcessedTx, NestedProcessReturnValues[]]> { const timer = new Timer(); - const { tailKernelOutput, returnValues, revertReason, provingRequests, gasUsed, processedPhases } = + const { avmProvingRequest, tailKernelOutput, returnValues, revertReason, gasUsed, processedPhases } = await this.enqueuedCallsProcessor.process(tx); if (!tailKernelOutput) { @@ -279,7 +279,7 @@ export class PublicProcessor { const phaseCount = processedPhases.length; this.metrics.recordTx(phaseCount, timer.ms()); - const processedTx = makeProcessedTx(tx, tailKernelOutput, provingRequests, revertReason, gasUsed); + const processedTx = makeProcessedTx(tx, tailKernelOutput, { avmProvingRequest, revertReason, gasUsed }); return [processedTx, returnValues]; } } diff --git a/yarn-project/simulator/src/rollup/index.ts b/yarn-project/simulator/src/rollup/index.ts deleted file mode 100644 index f35e118a5a16..000000000000 --- a/yarn-project/simulator/src/rollup/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './rollup.js'; diff --git a/yarn-project/simulator/src/rollup/rollup.ts b/yarn-project/simulator/src/rollup/rollup.ts deleted file mode 100644 index 8ee8b036ca79..000000000000 --- a/yarn-project/simulator/src/rollup/rollup.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { type CircuitSimulationStats } from '@aztec/circuit-types/stats'; -import { - type BaseOrMergeRollupPublicInputs, - type BaseParityInputs, - type BaseRollupInputs, - type BlockMergeRollupInputs, - type BlockRootOrBlockMergePublicInputs, - type BlockRootRollupInputs, - type MergeRollupInputs, - type ParityPublicInputs, - type RootParityInputs, - type RootRollupInputs, - type RootRollupPublicInputs, -} from '@aztec/circuits.js'; -import { createDebugLogger } from '@aztec/foundation/log'; -import { elapsed } from '@aztec/foundation/timer'; -import { - SimulatedServerCircuitArtifacts, - convertBaseParityInputsToWitnessMap, - convertBaseParityOutputsFromWitnessMap, - convertBlockMergeRollupInputsToWitnessMap, - convertBlockMergeRollupOutputsFromWitnessMap, - convertBlockRootRollupInputsToWitnessMap, - convertBlockRootRollupOutputsFromWitnessMap, - convertMergeRollupInputsToWitnessMap, - convertMergeRollupOutputsFromWitnessMap, - convertRootParityInputsToWitnessMap, - convertRootParityOutputsFromWitnessMap, - convertRootRollupInputsToWitnessMap, - convertRootRollupOutputsFromWitnessMap, - convertSimulatedBaseRollupInputsToWitnessMap, - convertSimulatedBaseRollupOutputsFromWitnessMap, -} from '@aztec/noir-protocol-circuits-types'; - -import { WASMSimulator } from '../providers/acvm_wasm.js'; -import { type SimulationProvider } from '../providers/simulation_provider.js'; - -/** - * Circuit simulator for the rollup circuits. - */ -export interface RollupSimulator { - /** - * Simulates the base parity circuit from its inputs. - * @param inputs - Inputs to the circuit. - * @returns The public inputs of the parity circuit. - */ - baseParityCircuit(inputs: BaseParityInputs): Promise; - /** - * Simulates the root parity circuit from its inputs. - * @param inputs - Inputs to the circuit. - * @returns The public inputs of the parity circuit. - */ - rootParityCircuit(inputs: RootParityInputs): Promise; - /** - * Simulates the base rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - baseRollupCircuit(input: BaseRollupInputs): Promise; - /** - * Simulates the merge rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - mergeRollupCircuit(input: MergeRollupInputs): Promise; - /** - * Simulates the block root rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - blockRootRollupCircuit(input: BlockRootRollupInputs): Promise; - /** - * Simulates the block merge rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - blockMergeRollupCircuit(input: BlockMergeRollupInputs): Promise; - /** - * Simulates the root rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - rootRollupCircuit(input: RootRollupInputs): Promise; -} - -/** - * Implements the rollup circuit simulator. - */ -export class RealRollupCircuitSimulator implements RollupSimulator { - private log = createDebugLogger('aztec:rollup-simulator'); - - // Some circuits are so small it is faster to use WASM - private wasmSimulator: WASMSimulator = new WASMSimulator(); - - constructor(private simulationProvider: SimulationProvider) {} - - /** - * Simulates the base parity circuit from its inputs. - * @param inputs - Inputs to the circuit. - * @returns The public inputs of the parity circuit. - */ - public async baseParityCircuit(inputs: BaseParityInputs): Promise { - const witnessMap = convertBaseParityInputsToWitnessMap(inputs); - - const witness = await this.simulationProvider.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BaseParityArtifact, - ); - - const result = convertBaseParityOutputsFromWitnessMap(witness); - - return Promise.resolve(result); - } - - /** - * Simulates the root parity circuit from its inputs. - * @param inputs - Inputs to the circuit. - * @returns The public inputs of the parity circuit. - */ - public async rootParityCircuit(inputs: RootParityInputs): Promise { - const witnessMap = convertRootParityInputsToWitnessMap(inputs); - - const witness = await this.simulationProvider.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.RootParityArtifact, - ); - - const result = convertRootParityOutputsFromWitnessMap(witness); - - return Promise.resolve(result); - } - - /** - * Simulates the base rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async baseRollupCircuit(input: BaseRollupInputs): Promise { - const witnessMap = convertSimulatedBaseRollupInputsToWitnessMap(input); - - const witness = await this.simulationProvider.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BaseRollupArtifact, - ); - - const result = convertSimulatedBaseRollupOutputsFromWitnessMap(witness); - - return Promise.resolve(result); - } - - /** - * Simulates the merge rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async mergeRollupCircuit(input: MergeRollupInputs): Promise { - const witnessMap = convertMergeRollupInputsToWitnessMap(input); - - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.MergeRollupArtifact, - ); - - const result = convertMergeRollupOutputsFromWitnessMap(witness); - - return result; - } - - /** - * Simulates the block root rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async blockRootRollupCircuit(input: BlockRootRollupInputs): Promise { - const witnessMap = convertBlockRootRollupInputsToWitnessMap(input); - - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BlockRootRollupArtifact, - ); - - const result = convertBlockRootRollupOutputsFromWitnessMap(witness); - - return Promise.resolve(result); - } - - /** - * Simulates the block merge rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async blockMergeRollupCircuit(input: BlockMergeRollupInputs): Promise { - const witnessMap = convertBlockMergeRollupInputsToWitnessMap(input); - - const witness = await this.wasmSimulator.simulateCircuit( - witnessMap, - SimulatedServerCircuitArtifacts.BlockMergeRollupArtifact, - ); - - const result = convertBlockMergeRollupOutputsFromWitnessMap(witness); - - return Promise.resolve(result); - } - - /** - * Simulates the root rollup circuit from its inputs. - * @param input - Inputs to the circuit. - * @returns The public inputs as outputs of the simulation. - */ - public async rootRollupCircuit(input: RootRollupInputs): Promise { - const witnessMap = convertRootRollupInputsToWitnessMap(input); - - const [duration, witness] = await elapsed(() => - this.wasmSimulator.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts.RootRollupArtifact), - ); - - const result = convertRootRollupOutputsFromWitnessMap(witness); - - this.log.debug(`Simulated root rollup circuit`, { - eventName: 'circuit-simulation', - circuitName: 'root-rollup', - duration, - inputSize: input.toBuffer().length, - outputSize: result.toBuffer().length, - } satisfies CircuitSimulationStats); - return result; - } -}