From 15a522ba731820851f1bf505bc2663314e4efc30 Mon Sep 17 00:00:00 2001 From: Dan Lee <142251406+dan-aztec@users.noreply.github.com> Date: Thu, 16 Nov 2023 03:52:43 -0800 Subject: [PATCH] feat: public kernel in noir (#3186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit starting rewrite based off of https://github.com/AztecProtocol/aztec-packages/pull/2740 literal cpp -> noir translation for first conversion --------- Co-authored-by: kevaundray Co-authored-by: Álvaro Rodríguez Co-authored-by: Leila Wang --- .../benchmarks/bench_publish_rollup.test.ts | 2 +- .../noir-protocol-circuits/src/Nargo.toml | 4 + .../src/__snapshots__/index.test.ts.snap | 4 + .../src/crates/public-kernel-lib/Nargo.toml | 9 + .../src/crates/public-kernel-lib/src/abis.nr | 1 + .../src/abis/public_call_data.nr | 15 + .../crates/public-kernel-lib/src/common.nr | 357 ++++++++++++++++++ .../src/crates/public-kernel-lib/src/hash.nr | 19 + .../src/crates/public-kernel-lib/src/lib.nr | 11 + .../src/public_kernel_private_previous.nr | 55 +++ .../src/public_kernel_public_previous.nr | 49 +++ .../Nargo.toml | 10 + .../src/main.nr | 6 + .../public-kernel-private-previous/Nargo.toml | 10 + .../src/main.nr | 6 + .../Nargo.toml | 10 + .../src/main.nr | 6 + .../public-kernel-public-previous/Nargo.toml | 10 + .../public-kernel-public-previous/src/main.nr | 6 + .../crates/types/src/abis/call_stack_item.nr | 26 +- .../src/abis/private_circuit_public_inputs.nr | 2 + .../src/abis/public_circuit_public_inputs.nr | 2 + .../crates/types/src/abis/public_data_read.nr | 11 + .../src/abis/public_data_update_request.nr | 12 + .../src/crates/types/src/interop_testing.nr | 50 ++- .../noir-protocol-circuits/src/index.test.ts | 22 ++ .../noir-protocol-circuits/src/index.ts | 103 ++++- .../src/scripts/generate_ts_from_abi.ts | 2 + .../src/target/private_kernel_init.json | 2 +- .../target/private_kernel_init_simulated.json | 2 +- .../src/target/private_kernel_inner.json | 2 +- .../private_kernel_inner_simulated.json | 2 +- .../src/target/private_kernel_ordering.json | 2 +- .../private_kernel_ordering_simulated.json | 2 +- .../public_kernel_private_previous.json | 1 + ...lic_kernel_private_previous_simulated.json | 1 + .../target/public_kernel_public_previous.json | 1 + ...blic_kernel_public_previous_simulated.json | 1 + .../src/target/rollup_merge.json | 2 +- .../src/target/rollup_root.json | 2 +- .../src/type_conversion.ts | 110 ++++++ .../public_kernel_private_previous_types.ts | 200 ++++++++++ .../public_kernel_public_previous_types.ts | 200 ++++++++++ .../src/sequencer/public_processor.ts | 6 +- .../src/simulator/public_kernel.ts | 7 +- 45 files changed, 1342 insertions(+), 21 deletions(-) create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/Nargo.toml create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis/public_call_data.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/hash.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/lib.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/Nargo.toml create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/src/main.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/Nargo.toml create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/src/main.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/Nargo.toml create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/src/main.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/Nargo.toml create mode 100644 yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/src/main.nr create mode 100644 yarn-project/noir-protocol-circuits/src/target/public_kernel_private_previous.json create mode 100644 yarn-project/noir-protocol-circuits/src/target/public_kernel_private_previous_simulated.json create mode 100644 yarn-project/noir-protocol-circuits/src/target/public_kernel_public_previous.json create mode 100644 yarn-project/noir-protocol-circuits/src/target/public_kernel_public_previous_simulated.json create mode 100644 yarn-project/noir-protocol-circuits/src/types/public_kernel_private_previous_types.ts create mode 100644 yarn-project/noir-protocol-circuits/src/types/public_kernel_public_previous_types.ts diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index 7e191cee1b3..61b3359d250 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -24,7 +24,7 @@ describe('benchmarks/publish_rollup', () => { // Simulate and simultaneously send ROLLUP_SIZE txs. These should not yet be processed since sequencer is stopped. context.logger(`Assembling rollup with ${txCount} txs`); const sentTxs = await sendTxs(txCount, context, contract); - + context.logger.info(`Sent ${txCount} txs`); // Restart sequencer to process all txs together sequencer.restart(); diff --git a/yarn-project/noir-protocol-circuits/src/Nargo.toml b/yarn-project/noir-protocol-circuits/src/Nargo.toml index 232b37c5650..bc1c583a083 100644 --- a/yarn-project/noir-protocol-circuits/src/Nargo.toml +++ b/yarn-project/noir-protocol-circuits/src/Nargo.toml @@ -8,6 +8,10 @@ members = [ "crates/private-kernel-inner-simulated", "crates/private-kernel-ordering", "crates/private-kernel-ordering-simulated", + "crates/public-kernel-private-previous", + "crates/public-kernel-private-previous-simulated", + "crates/public-kernel-public-previous", + "crates/public-kernel-public-previous-simulated", "crates/rollup-lib", "crates/rollup-merge", "crates/rollup-base", diff --git a/yarn-project/noir-protocol-circuits/src/__snapshots__/index.test.ts.snap b/yarn-project/noir-protocol-circuits/src/__snapshots__/index.test.ts.snap index 8d44dc24e57..e7210994b67 100644 --- a/yarn-project/noir-protocol-circuits/src/__snapshots__/index.test.ts.snap +++ b/yarn-project/noir-protocol-circuits/src/__snapshots__/index.test.ts.snap @@ -20,6 +20,10 @@ exports[`Noir compatibility tests (interop_testing.nr) ComputeContractAddressFro exports[`Noir compatibility tests (interop_testing.nr) Function leaf matches noir 1`] = `"0x1ad8ece7f40e63d011ae47c6ce6cdaf31d632a23f5cf35bbeaaf69c8302afdbc"`; +exports[`Noir compatibility tests (interop_testing.nr) Public call stack item matches noir 1`] = `"0x0a370c67b66e30901470c11a199764a914fc0fcfbc737ed03153079b2765813a"`; + +exports[`Noir compatibility tests (interop_testing.nr) Public call stack item request matches noir 1`] = `"0x1d51d7758d792c9cd6edd8e8ec5f1f9fb1f974abc1af6bb4cf9f2328ef306c96"`; + exports[`Noir compatibility tests (interop_testing.nr) TxRequest Hash matches Noir 1`] = `"0x0b487ff2900ae1178e131bfe333fdbc351beef658f7c0d62db2801429b1aab75"`; exports[`Private kernel Executes private kernel init circuit for a contract deployment 1`] = ` diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/Nargo.toml b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/Nargo.toml new file mode 100644 index 00000000000..76525900176 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "public_kernel_lib" +type = "lib" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +aztec = { path = "../../../../aztec-nr/aztec" } +types = { path = "../types" } diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis.nr new file mode 100644 index 00000000000..3df2e439ea9 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis.nr @@ -0,0 +1 @@ +mod public_call_data; \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis/public_call_data.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis/public_call_data.nr new file mode 100644 index 00000000000..c2c544c7968 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/abis/public_call_data.nr @@ -0,0 +1,15 @@ +use dep::aztec::constants_gen::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}; +use dep::types::address::{Address, EthAddress}; +use dep::types::utils::bounded_vec::BoundedVec; +use dep::types::abis::call_stack_item::PublicCallStackItem; +use dep::types::mocked::Proof; + +struct PublicCallData { + call_stack_item: PublicCallStackItem, + public_call_stack_preimages: [PublicCallStackItem; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + + proof: Proof, + portal_contract_address: EthAddress, + bytecode_hash: Field, + +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr new file mode 100644 index 00000000000..d5818ce603c --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr @@ -0,0 +1,357 @@ +use dep::types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs; +use dep::types::abis::kernel_circuit_public_inputs::KernelCircuitPublicInputsBuilder; +use dep::types::utils::arrays; +use dep::types::abis::previous_kernel_data::PreviousKernelData; +use dep::types::abis::combined_accumulated_data::{CombinedAccumulatedData, CombinedAccumulatedDataBuilder}; +use crate::hash::{compute_public_data_tree_index, compute_public_data_tree_value}; +use dep::types::hash::{silo_commitment, silo_nullifier, compute_l2_to_l1_hash, accumulate_sha256}; +use dep::types::address::Address; +use dep::types::abis::new_contract_data::NewContractData; +use dep::types::abis::complete_address::CompleteAddress; +use dep::types::utils::bounded_vec::BoundedVec; +use crate::abis::public_call_data::PublicCallData; +use dep::types::abis::call_stack_item::PublicCallStackItem; +use dep::types::abis::public_data_update_request::PublicDataUpdateRequest; +use dep::types::contrakt::storage_read::StorageRead; +use dep::types::abis::public_data_read::PublicDataRead; +use dep::types::utils::uint128::U128; + +use dep::aztec::constants_gen::{ + MAX_READ_REQUESTS_PER_CALL, + MAX_NEW_NULLIFIERS_PER_CALL, + EMPTY_NULLIFIED_COMMITMENT, + MAX_NEW_L2_TO_L1_MSGS_PER_CALL, + MAX_NEW_COMMITMENTS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_CALL, +}; + +// Validate that all pre-images on the call stack hash to equal the accumulated data +pub fn validate_call_stack(public_call : PublicCallData) { + let stack = public_call.call_stack_item.public_inputs.public_call_stack; + let preimages = public_call.public_call_stack_preimages; + + let our_contract_address = public_call.call_stack_item.contract_address; + let our_storage_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; + let our_msg_sender = public_call.call_stack_item.public_inputs.call_context.msg_sender; + let our_portal_contract_address = + public_call.call_stack_item.public_inputs.call_context.portal_contract_address; + + assert(stack.len() == preimages.len()); // This is not in the cpp code. + for i in 0..stack.len() { + let hash = stack[i]; + let preimage = preimages[i]; + + let is_delegate_call = preimage.public_inputs.call_context.is_delegate_call; + let is_static_call = preimage.public_inputs.call_context.is_static_call; + let contract_being_called = preimage.contract_address; + + // Note: this assumes it's computationally infeasible to have `0` as a valid call_stack_item_hash. + // Assumes `hash == 0` means "this stack item is empty". + + let calculated_hash = if hash == 0 { + 0 + } else { + preimage.hash() + }; + if calculated_hash != 0 { + assert(hash == calculated_hash, "call stack item hash doesn't match preimage hash"); + // here we validate the msg sender for each call on the stack + // here we validate the storage address for each call on the stack + // we need to consider regular vs delegate calls for both + let preimage_msg_sender = preimage.public_inputs.call_context.msg_sender; + let preimage_storage_address = preimage.public_inputs.call_context.storage_contract_address; + + if is_delegate_call { + assert(preimage_msg_sender.eq(our_msg_sender), "call_stack_msg_sender doesn't match expected_msg_sender"); + assert(preimage_storage_address.eq(our_storage_address), "call_stack_storage_address doesnt match expected_storage_address"); + // if it is a delegate call then we check that the portal contract in the pre image is our portal contract + let preimage_portal_address = preimage.public_inputs.call_context.portal_contract_address; + let expected_portal_address = our_portal_contract_address; + assert(preimage_portal_address.eq(expected_portal_address), "call_stack_portal_contract_address doesnt match expected_portal_address"); + } else { + assert(preimage_msg_sender.eq(our_contract_address), "call_stack_msg_sender doesn't match expected_msg_sender"); + assert(preimage_storage_address.eq(contract_being_called), "call_stack_storage_address doesnt match expected_storage_address"); + } + + + let num_contract_storage_update_requests = preimage.public_inputs.contract_storage_update_requests.len(); + if is_static_call { + assert(num_contract_storage_update_requests == 0,"contract_storage_update_requests should be empty for static call"); + } + } + } +} + +// Validates the call context of the current iteration +pub fn validate_call_context(public_call: PublicCallData){ + let call_stack_item = public_call.call_stack_item; + let is_delegate_call = call_stack_item.public_inputs.call_context.is_delegate_call; + let is_static_call = call_stack_item.public_inputs.call_context.is_static_call; + let contract_address = call_stack_item.contract_address; + let storage_contract_address = call_stack_item.public_inputs.call_context.storage_contract_address; + let contract_storage_update_requests_length = + call_stack_item.public_inputs.contract_storage_update_requests.len(); + + if is_delegate_call{ + assert(!contract_address.eq(storage_contract_address), + "curent contract address must not match storage contract address for delegate calls"); + } + if is_static_call { + + assert(contract_storage_update_requests_length == 0, + "No contract storage update requests are allowed for static calls"); + } +} + +// Validates the kernel execution of the current iteration +pub fn validate_kernel_execution(public_call: PublicCallData) { + validate_call_context(public_call); + validate_call_stack(public_call); +} + +//Validates inputs to the kernel circuit that are common to all invocation scenarios +pub fn validate_inputs(public_call: PublicCallData){ + // Validates commons inputs for all type of kernel inputs + let this_call_stack_item: PublicCallStackItem = public_call.call_stack_item; + assert(this_call_stack_item.public_inputs.call_context.is_contract_deployment == false, + "Contract deployment can't be a public function"); + assert(!this_call_stack_item.contract_address.eq(Address::ZERO()), + "Contract address must be non-zero"); + assert(this_call_stack_item.function_data.selector.to_field() != 0, + "Function signature must be non-zero"); + assert(this_call_stack_item.function_data.is_constructor == false, + "Constructors can't be public functions"); + assert(this_call_stack_item.function_data.is_private == false, + "Cannot execute a private function with the public kernel circuit"); + assert(public_call.bytecode_hash != 0, + "Bytecode hash must be non-zero"); + + if (this_call_stack_item.function_data.is_internal) { + let target = this_call_stack_item.contract_address; + let sender = this_call_stack_item.public_inputs.call_context.msg_sender; + + assert(target.eq(sender), "call is internal, but msg_sender is not self"); + } +} + +pub fn perform_static_call_checks(public_call: PublicCallData){ + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + + let is_static_call = public_call_public_inputs.call_context.is_static_call; + // If the call is a static call, there should be no new commitments or nullifiers. + let new_commitments = public_call_public_inputs.new_commitments; + let new_nullifiers = public_call_public_inputs.new_nullifiers; + + if (is_static_call) { + // No state changes are allowed for static calls: + assert(arrays::is_empty_array(new_commitments), "new_commitments must be empty for static calls"); + assert(arrays::is_empty_array(new_nullifiers), "new_nullifiers must be empty for static calls"); + } +} + +pub fn propagate_valid_public_data_update_requests(public_call: PublicCallData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder){ + let contract_address = public_call.call_stack_item.contract_address; + let update_requests = public_call.call_stack_item.public_inputs.contract_storage_update_requests; + + let mut public_data_update_requests : BoundedVec = BoundedVec::new(PublicDataUpdateRequest::empty()); + + assert(update_requests.len() == MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX); // This is not done in the cpp code. + + for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { + let update_request = update_requests[i]; + if (!update_request.is_empty()) { + let public_data_update_request = PublicDataUpdateRequest { + leaf_index: compute_public_data_tree_index(contract_address, update_request.storage_slot), + old_value: compute_public_data_tree_value(update_request.old_value), + new_value: compute_public_data_tree_value(update_request.new_value), + }; + + public_data_update_requests.push(public_data_update_request); + } + } + circuit_outputs.end.public_data_update_requests.push_vec(public_data_update_requests); + +} + + +pub fn initialize_end_values(previous_kernel : PreviousKernelData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder) { + // Initialises the circuit outputs with the end state of the previous iteration + circuit_outputs.constants = previous_kernel.public_inputs.constants; + + // Ensure the arrays are the same as previously, before we start pushing more data onto them in other + // functions within this circuit: + let start = previous_kernel.public_inputs.end; + + circuit_outputs.end.new_commitments = arrays::array_to_bounded_vec(start.new_commitments, arrays::is_empty, 0); + circuit_outputs.end.new_nullifiers = arrays::array_to_bounded_vec(start.new_nullifiers, arrays::is_empty, 0); + + circuit_outputs.end.private_call_stack = arrays::array_to_bounded_vec(start.private_call_stack, arrays::is_empty, 0); + circuit_outputs.end.public_call_stack = arrays::array_to_bounded_vec(start.public_call_stack, arrays::is_empty, 0); + circuit_outputs.end.new_l2_to_l1_msgs = arrays::array_to_bounded_vec(start.new_l2_to_l1_msgs, arrays::is_empty, 0); + + circuit_outputs.end.optionally_revealed_data = start.optionally_revealed_data; + + circuit_outputs.end.public_data_update_requests = arrays::array_to_bounded_vec(start.public_data_update_requests, |pdu: PublicDataUpdateRequest| pdu.is_empty(), PublicDataUpdateRequest::empty()); + circuit_outputs.end.public_data_reads = arrays::array_to_bounded_vec(start.public_data_reads, |pdr: PublicDataRead| pdr.is_empty(), PublicDataRead::empty()); + + // Public kernel does not modify encrypted logs values --> we just copy them to output + circuit_outputs.end.encrypted_logs_hash = start.encrypted_logs_hash; + circuit_outputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; + + circuit_outputs.end.new_contracts = arrays::array_to_bounded_vec(previous_kernel.public_inputs.end.new_contracts, |ncd: NewContractData| ncd.is_empty(), NewContractData::default()); +} + +pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs : &mut KernelCircuitPublicInputsBuilder) { + // Updates the circuit outputs with new state changes, call stack etc + circuit_outputs.is_private = false; + + // If this call is a static call, certain operations are disallowed, such as creating new state. + perform_static_call_checks(public_call); + + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + + let public_call_stack = arrays::array_to_bounded_vec(public_call_public_inputs.public_call_stack, arrays::is_empty, 0); + circuit_outputs.end.public_call_stack.push_vec(public_call_stack); + + // don't update pending_read_requests, because those just get passed through without any change + + propagate_new_nullifiers(public_call, circuit_outputs); + propagate_new_commitments(public_call, circuit_outputs); + + propagate_new_l2_to_l1_messages(public_call, circuit_outputs); + + propagate_valid_public_data_update_requests(public_call, circuit_outputs); + + propagate_valid_public_data_reads(public_call, circuit_outputs); +} + +pub fn propagate_valid_public_data_reads(public_call: PublicCallData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder){ + let contract_address = public_call.call_stack_item.contract_address; + let read_requests = public_call.call_stack_item.public_inputs.contract_storage_reads; + + let mut public_data_reads : BoundedVec = BoundedVec::new(PublicDataRead::empty()); + + for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { + let read_request: StorageRead = read_requests[i]; + if !read_request.is_empty() { + let public_data_read = PublicDataRead { + leaf_index: compute_public_data_tree_index(contract_address, read_request.storage_slot), + value: compute_public_data_tree_value(read_request.current_value), + }; + public_data_reads.push(public_data_read); + } + } + circuit_outputs.end.public_data_reads.push_vec(public_data_reads); +} + +pub fn propagate_new_commitments(public_call: PublicCallData, circuit_outputs : &mut KernelCircuitPublicInputsBuilder) { + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + + let new_commitments = public_call.call_stack_item.public_inputs.new_commitments; + let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; + + let mut siloed_new_commitments : BoundedVec = BoundedVec::new(0); + assert(new_commitments.len() == MAX_NEW_COMMITMENTS_PER_CALL); + for i in 0..MAX_NEW_COMMITMENTS_PER_CALL { + let new_commitment = new_commitments[i]; + if new_commitment != 0 { + siloed_new_commitments.push(silo_commitment(storage_contract_address, new_commitment)); + } + } + circuit_outputs.end.new_commitments.push_vec(siloed_new_commitments); +} + +pub fn propagate_new_nullifiers(public_call: PublicCallData, circuit_outputs : &mut KernelCircuitPublicInputsBuilder) { + let new_nullifiers = public_call.call_stack_item.public_inputs.new_nullifiers; + let storage_contract_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; + + // Enhance commitments and nullifiers with domain separation whereby domain is the contract. + let mut siloed_new_nullifiers : BoundedVec = BoundedVec::new(0); + assert(new_nullifiers.len() == MAX_NEW_NULLIFIERS_PER_CALL); + for i in 0..MAX_NEW_NULLIFIERS_PER_CALL { + let new_nullifier = new_nullifiers[i]; + if new_nullifier != 0 { + siloed_new_nullifiers.push(silo_nullifier(storage_contract_address, new_nullifier)); + } + } + + circuit_outputs.end.new_nullifiers.push_vec(siloed_new_nullifiers); +} + + +pub fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: &mut KernelCircuitPublicInputsBuilder){ + // new l2 to l1 messages + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + let portal_contract_address = public_call.portal_contract_address; + let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; + + let new_l2_to_l1_msgs = public_call_public_inputs.new_l2_to_l1_msgs; + let mut new_l2_to_l1_msgs_to_insert : BoundedVec = BoundedVec::new(0); + for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL { + let msg_is_zero = new_l2_to_l1_msgs[i] == 0; + if msg_is_zero == false { + let new_l2_to_l1_msgs = compute_l2_to_l1_hash(storage_contract_address, + public_inputs.constants.tx_context.version, + portal_contract_address, + public_inputs.constants.tx_context.chain_id, + new_l2_to_l1_msgs[i]); + new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) + } + } + public_inputs.end.new_l2_to_l1_msgs.push_vec(new_l2_to_l1_msgs_to_insert); +} + +/** + * @brief Accumulates unencrypted logs hashes and lengths. + * @param The type of kernel input + * @param public_kernel_inputs The inputs to this iteration of the kernel circuit + * @param circuit_outputs The circuit outputs to be populated + * @note See the following thread if not clear: + * https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 + * @note Used by public kernels which had previous iterations. + */ +pub fn accumulate_unencrypted_logs(public_call: PublicCallData, + previous_kernel: PreviousKernelData, + public_inputs: &mut KernelCircuitPublicInputsBuilder) +{ + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + + let previous_kernel_end = previous_kernel.public_inputs.end; + let previous_unencrypted_logs_hash = previous_kernel_end.unencrypted_logs_hash; + + let current_unencrypted_logs_hash = public_call_public_inputs.unencrypted_logs_hash; + public_inputs.end.unencrypted_logs_hash = accumulate_sha256([ + U128::from_field(previous_unencrypted_logs_hash[0]), + U128::from_field(previous_unencrypted_logs_hash[1]), + U128::from_field(current_unencrypted_logs_hash[0]), + U128::from_field(current_unencrypted_logs_hash[1]) + ]); + + // Add log preimages lengths from current iteration to accumulated lengths + let current_unencrypted_log_preimages_length = public_call_public_inputs.unencrypted_log_preimages_length; + public_inputs.end.unencrypted_log_preimages_length = + previous_kernel_end.unencrypted_log_preimages_length + current_unencrypted_log_preimages_length; +} + + +/** + * @brief Validates that the call stack item for this circuit iteration is at the top of the call stack + * @param builder The circuit builder + * @param public_kernel_inputs The inputs to this iteration of the kernel circuit + */ + pub fn validate_this_public_call_hash(public_call: PublicCallData, public_inputs: &mut KernelCircuitPublicInputsBuilder) { + // If public call stack is empty, we bail so array_pop doesn't throw_or_abort + assert(public_inputs.end.public_call_stack.len() != 0 , "Public call stack can't be empty"); + + // Pops the current function execution from the stack and validates it against the call stack item + + // TODO: this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' tx, + // and the 'gas rebate' tx). + let popped_public_call_hash = public_inputs.end.public_call_stack.pop(); + let calculated_this_public_call_hash = public_call.call_stack_item.hash(); + + assert( + popped_public_call_hash == calculated_this_public_call_hash, + "calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the call stack"); +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/hash.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/hash.nr new file mode 100644 index 00000000000..7a3cc9a5f0e --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/hash.nr @@ -0,0 +1,19 @@ +use dep::types::address::Address; +use dep::aztec::{ + constants_gen, + constants_gen::{GENERATOR_INDEX__PUBLIC_LEAF_INDEX}, + hash::sha256_to_field, +}; + +pub fn compute_public_data_tree_index(contract_address: Address, storage_slot: Field) -> Field { + dep::std::hash::pedersen_hash_with_separator([ + contract_address.to_field(), + storage_slot + ], constants_gen::GENERATOR_INDEX__PUBLIC_LEAF_INDEX) +} + +pub fn compute_public_data_tree_value(value: Field) -> Field { + // as it's a public value, it doesn't require hashing. + // leaving this function here in case we decide to change this. + value +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/lib.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/lib.nr new file mode 100644 index 00000000000..a00a878af9d --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/lib.nr @@ -0,0 +1,11 @@ +mod abis; +// TODO: rename to be precise as to what its common to (the public kernel circuits). +mod common; + +mod hash; + +mod public_kernel_private_previous; +mod public_kernel_public_previous; + +use public_kernel_private_previous::PublicKernelPrivatePreviousInputs; +use public_kernel_public_previous::PublicKernelPublicPreviousInputs; diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr new file mode 100644 index 00000000000..14cbfb2619e --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr @@ -0,0 +1,55 @@ +use crate::abis::public_call_data::PublicCallData; +use dep::types::abis::previous_kernel_data::PreviousKernelData; +use dep::types::abis::kernel_circuit_public_inputs::{KernelCircuitPublicInputs, KernelCircuitPublicInputsBuilder}; +use crate::common; +use dep::std::unsafe; +// translated from cpp impl in +// aztec-packages/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp + +struct PublicKernelPrivatePreviousInputs { + previous_kernel: PreviousKernelData, + public_call: PublicCallData, +} + +impl PublicKernelPrivatePreviousInputs { + + fn validate_inputs(self) { + let private_call_stack = self.previous_kernel.public_inputs.end.private_call_stack; + for i in 0..private_call_stack.len() { + let private_call = private_call_stack[i]; + assert(private_call == 0, + "Private call stack must be empty when executing in the public kernel (i.e. all private calls must have been completed)"); + } + + let previous_call_is_private = self.previous_kernel.public_inputs.is_private; + assert(previous_call_is_private == true, + "Previous kernel must be private when in this public kernel version"); + } + + + fn public_kernel_private_previous(self) -> KernelCircuitPublicInputs { + // construct the circuit outputs + let mut public_inputs: KernelCircuitPublicInputsBuilder = unsafe::zeroed(); + + // initialise the end state with our provided previous kernel state + common::initialize_end_values(self.previous_kernel, &mut public_inputs); + + // validate the inputs common to all invocation circumstances + common::validate_inputs(self.public_call); + + // validate the inputs unique to having a previous private kernel + self.validate_inputs(); + + // validate the kernel execution common to all invocation circumstances + common::validate_kernel_execution(self.public_call); + + // validate our public call hash + common::validate_this_public_call_hash(self.public_call,&mut public_inputs); + + common::update_public_end_values(self.public_call,&mut public_inputs); + + common::accumulate_unencrypted_logs(self.public_call, self.previous_kernel,&mut public_inputs); + + public_inputs.finish() + } +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr new file mode 100644 index 00000000000..8fbdaefc6f9 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr @@ -0,0 +1,49 @@ +use crate::abis::public_call_data::PublicCallData; +use dep::types::abis::previous_kernel_data::PreviousKernelData; +use dep::types::KernelCircuitPublicInputs; +use dep::types::abis::kernel_circuit_public_inputs::KernelCircuitPublicInputsBuilder; +use crate::common; +use dep::std::unsafe; + + +struct PublicKernelPublicPreviousInputs { + previous_kernel: PreviousKernelData, + public_call: PublicCallData, +} + +impl PublicKernelPublicPreviousInputs { + +// this is the only difference between the two PublicKernels' logic: + fn validate_inputs(self) { + let previous_call_is_private = self.previous_kernel.public_inputs.is_private; + assert(previous_call_is_private == false, + "Previous kernel must be public when in this public kernel version"); + } + + + fn public_kernel_public_previous(self) -> KernelCircuitPublicInputs { + // construct the circuit outputs + let mut public_inputs: KernelCircuitPublicInputsBuilder = unsafe::zeroed(); + + // initialise the end state with our provided previous kernel state + common::initialize_end_values(self.previous_kernel, &mut public_inputs); + + // validate the inputs common to all invocation circumstances + common::validate_inputs(self.public_call); + + // validate the inputs unique to having a previous public kernel + self.validate_inputs(); + + // validate the kernel execution common to all invocation circumstances + common::validate_kernel_execution(self.public_call); + + // validate our public call hash + common::validate_this_public_call_hash(self.public_call, &mut public_inputs); + + common::update_public_end_values(self.public_call,&mut public_inputs); + + common::accumulate_unencrypted_logs(self.public_call, self.previous_kernel,&mut public_inputs); + + public_inputs.finish() + } +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/Nargo.toml b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/Nargo.toml new file mode 100644 index 00000000000..d131d25b72c --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "public_kernel_private_previous_simulated" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +types = { path = "../types" } +public_kernel_lib = { path = "../public-kernel-lib" } +aztec = { path = "../../../../aztec-nr/aztec" } diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/src/main.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/src/main.nr new file mode 100644 index 00000000000..df611bf80db --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous-simulated/src/main.nr @@ -0,0 +1,6 @@ +use dep::public_kernel_lib::{PublicKernelPrivatePreviousInputs}; +use dep::types::{KernelCircuitPublicInputs}; + +unconstrained fn main(input: PublicKernelPrivatePreviousInputs) -> distinct pub KernelCircuitPublicInputs { + input.public_kernel_private_previous() +} diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/Nargo.toml b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/Nargo.toml new file mode 100644 index 00000000000..a1aebfa70a6 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "public_kernel_private_previous" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +types = { path = "../types" } +public_kernel_lib = { path = "../public-kernel-lib" } +aztec = { path = "../../../../aztec-nr/aztec" } diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/src/main.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/src/main.nr new file mode 100644 index 00000000000..7ccd8c68502 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-private-previous/src/main.nr @@ -0,0 +1,6 @@ +use dep::public_kernel_lib::{PublicKernelPrivatePreviousInputs}; +use dep::types::{KernelCircuitPublicInputs}; + +fn main(input: PublicKernelPrivatePreviousInputs) -> distinct pub KernelCircuitPublicInputs { + input.public_kernel_private_previous() +} diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/Nargo.toml b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/Nargo.toml new file mode 100644 index 00000000000..5eb41be2441 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "public_kernel_public_previous_simulated" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +types = { path = "../types" } +public_kernel_lib = { path = "../public-kernel-lib" } +aztec = { path = "../../../../aztec-nr/aztec" } diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/src/main.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/src/main.nr new file mode 100644 index 00000000000..876d5c7684a --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous-simulated/src/main.nr @@ -0,0 +1,6 @@ +use dep::public_kernel_lib::{PublicKernelPublicPreviousInputs}; +use dep::types::{KernelCircuitPublicInputs}; + +unconstrained fn main(input: PublicKernelPublicPreviousInputs) -> distinct pub KernelCircuitPublicInputs { + input.public_kernel_public_previous() +} diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/Nargo.toml b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/Nargo.toml new file mode 100644 index 00000000000..9d972e291cc --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "public_kernel_public_previous" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +types = { path = "../types" } +public_kernel_lib = { path = "../public-kernel-lib" } +aztec = { path = "../../../../aztec-nr/aztec" } diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/src/main.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/src/main.nr new file mode 100644 index 00000000000..709dc8737ec --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-public-previous/src/main.nr @@ -0,0 +1,6 @@ +use dep::public_kernel_lib::{PublicKernelPublicPreviousInputs}; +use dep::types::{KernelCircuitPublicInputs}; + +fn main(input: PublicKernelPublicPreviousInputs) -> distinct pub KernelCircuitPublicInputs { + input.public_kernel_public_previous() +} diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/call_stack_item.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/call_stack_item.nr index fcf2b2dd0aa..fc6a754c50d 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/call_stack_item.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/call_stack_item.nr @@ -42,10 +42,30 @@ struct PublicCallStackItem { impl PublicCallStackItem { fn hash(self) -> Field { + let item = if self.is_execution_request { + self.as_execution_request() + } else { + self + }; + dep::std::hash::pedersen_hash_with_separator([ - self.contract_address.to_field(), - self.function_data.hash(), - self.public_inputs.hash(), + item.contract_address.to_field(), + item.function_data.hash(), + item.public_inputs.hash(), ], GENERATOR_INDEX__CALL_STACK_ITEM) } + + fn as_execution_request(self) -> Self { + let public_inputs = self.public_inputs; + let mut request_public_inputs: PublicCircuitPublicInputs = dep::std::unsafe::zeroed(); + request_public_inputs.call_context = public_inputs.call_context; + request_public_inputs.args_hash = public_inputs.args_hash; + + PublicCallStackItem { + contract_address: self.contract_address, + function_data: self.function_data, + is_execution_request: true, + public_inputs: request_public_inputs, + } + } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr index 80ab432850c..e46bf25f1d2 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr @@ -74,6 +74,8 @@ impl PrivateCircuitPublicInputs{ fields.push(self.chain_id); fields.push(self.version); + assert_eq(fields.len(), constants_gen::PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, "Incorrect number of input fields when hashing PrivateCircuitPublicInputs"); + dep::std::hash::pedersen_hash_with_separator(fields.storage, constants_gen::GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS) } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr index 94440204c37..5bb168296cb 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr @@ -64,6 +64,8 @@ impl PublicCircuitPublicInputs{ inputs.push_array(self.historical_block_data.to_array()); inputs.push(self.prover_address.to_field()); + assert_eq(inputs.len(), constants_gen::PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, "Incorrect number of input fields when hashing PublicCircuitPublicInputs"); + dep::std::hash::pedersen_hash_with_separator(inputs.storage, constants_gen::GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS) } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_read.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_read.nr index 60959fef603..3009efb2745 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_read.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_read.nr @@ -12,4 +12,15 @@ impl PublicDataRead { self.value, ], constants_gen::GENERATOR_INDEX__PUBLIC_DATA_READ) } + + pub fn empty() -> Self { + Self { + leaf_index : 0, + value : 0, + } + } + + pub fn is_empty(self) -> bool { + (self.leaf_index == 0) & (self.value == 0) + } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_update_request.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_update_request.nr index 10c7d3f9ffb..2ffdd3eeb30 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_update_request.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_data_update_request.nr @@ -7,6 +7,18 @@ struct PublicDataUpdateRequest { } impl PublicDataUpdateRequest { + pub fn empty() -> Self { + Self { + leaf_index : 0, + old_value : 0, + new_value : 0 + } + } + + pub fn is_empty(self) -> bool { + (self.leaf_index == 0) & (self.old_value == 0) & (self.new_value == 0) + } + fn hash(self) -> Field { dep::std::hash::pedersen_hash_with_separator([ self.leaf_index, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/interop_testing.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/interop_testing.nr index 3594f3e7d52..16c2115161e 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/interop_testing.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/interop_testing.nr @@ -8,7 +8,9 @@ use crate::abis::function_leaf_preimage::FunctionLeafPreimage; use crate::contrakt::deployment_data::ContractDeploymentData; use crate::abis::function_selector::FunctionSelector; use crate::hash::compute_l2_to_l1_hash; +use crate::abis::call_stack_item::PublicCallStackItem; use dep::aztec::hash::sha256_to_field; +use crate::abis::public_circuit_public_inputs::PublicCircuitPublicInputs; #[test] fn compute_complete_address() { @@ -96,4 +98,50 @@ fn compute_function_leaf() { }; assert_eq(leaf.hash(), 0x1ad8ece7f40e63d011ae47c6ce6cdaf31d632a23f5cf35bbeaaf69c8302afdbc); -} \ No newline at end of file +} + +#[test] +fn compute_call_stack_item_request() { + let contract_address = Address::from_field(1); + let function_data = FunctionData { + selector: FunctionSelector::from_u32(2), + is_internal: false, + is_private: false, + is_constructor: false, + }; + + let mut public_inputs: PublicCircuitPublicInputs = dep::std::unsafe::zeroed(); + public_inputs.new_commitments[0] = 1; + + let call_stack_item = PublicCallStackItem { + contract_address, + public_inputs, + is_execution_request: true, + function_data, + }; + + assert_eq(call_stack_item.hash(), 0x1d51d7758d792c9cd6edd8e8ec5f1f9fb1f974abc1af6bb4cf9f2328ef306c96); +} + +#[test] +fn compute_call_stack_item() { + let contract_address = Address::from_field(1); + let function_data = FunctionData { + selector: FunctionSelector::from_u32(2), + is_internal: false, + is_private: false, + is_constructor: false, + }; + + let mut public_inputs: PublicCircuitPublicInputs = dep::std::unsafe::zeroed(); + public_inputs.new_commitments[0] = 1; + + let call_stack_item = PublicCallStackItem { + contract_address, + public_inputs, + is_execution_request: false, + function_data, + }; + + assert_eq(call_stack_item.hash(), 0x0a370c67b66e30901470c11a199764a914fc0fcfbc737ed03153079b2765813a); +} diff --git a/yarn-project/noir-protocol-circuits/src/index.test.ts b/yarn-project/noir-protocol-circuits/src/index.test.ts index 893dcafc338..3e85e308ef2 100644 --- a/yarn-project/noir-protocol-circuits/src/index.test.ts +++ b/yarn-project/noir-protocol-circuits/src/index.test.ts @@ -40,6 +40,8 @@ import { PrivateKernelInputsInit, PrivateKernelInputsInner, PrivateKernelInputsOrdering, + PublicCallStackItem, + PublicCircuitPublicInputs, PublicDataRead, PublicDataUpdateRequest, RETURN_VALUES_LENGTH, @@ -461,6 +463,26 @@ describe('Noir compatibility tests (interop_testing.nr)', () => { const fnLeaf = computeFunctionLeaf(fnLeafPreimage); expect(fnLeaf.toString()).toMatchSnapshot(); }); + + it('Public call stack item matches noir', async () => { + const contractAddress = AztecAddress.fromField(new Fr(1)); + const functionData = new FunctionData(new FunctionSelector(2), false, false, false); + const appPublicInputs = PublicCircuitPublicInputs.empty(); + appPublicInputs.newCommitments[0] = new Fr(1); + + const publicCallStackItem = new PublicCallStackItem(contractAddress, functionData, appPublicInputs, false); + expect((await publicCallStackItem.hash()).toString()).toMatchSnapshot(); + }); + + it('Public call stack item request matches noir', async () => { + const contractAddress = AztecAddress.fromField(new Fr(1)); + const functionData = new FunctionData(new FunctionSelector(2), false, false, false); + const appPublicInputs = PublicCircuitPublicInputs.empty(); + appPublicInputs.newCommitments[0] = new Fr(1); + + const publicCallStackItem = new PublicCallStackItem(contractAddress, functionData, appPublicInputs, true); + expect((await publicCallStackItem.hash()).toString()).toMatchSnapshot(); + }); }); function numberToBuffer(value: number) { diff --git a/yarn-project/noir-protocol-circuits/src/index.ts b/yarn-project/noir-protocol-circuits/src/index.ts index 535b1bd8724..de1d8d5a111 100644 --- a/yarn-project/noir-protocol-circuits/src/index.ts +++ b/yarn-project/noir-protocol-circuits/src/index.ts @@ -6,6 +6,7 @@ import { PrivateKernelInputsInit, PrivateKernelInputsInner, PrivateKernelInputsOrdering, + PublicKernelInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; @@ -20,6 +21,10 @@ import PrivateKernelInnerJson from './target/private_kernel_inner.json' assert { import PrivateKernelInnerSimulatedJson from './target/private_kernel_inner_simulated.json' assert { type: 'json' }; import PrivateKernelOrderingJson from './target/private_kernel_ordering.json' assert { type: 'json' }; import PrivateKernelOrderingSimulatedJson from './target/private_kernel_ordering_simulated.json' assert { type: 'json' }; +import PublicKernelPrivatePreviousJson from './target/public_kernel_private_previous.json' assert { type: 'json' }; +import PublicKernelPrivatePreviousSimulatedJson from './target/public_kernel_private_previous_simulated.json' assert { type: 'json' }; +import PublicKernelPublicPreviousJson from './target/public_kernel_public_previous.json' assert { type: 'json' }; +import PublicKernelPublicPreviousSimulatedJson from './target/public_kernel_public_previous_simulated.json' assert { type: 'json' }; import MergeRollupJson from './target/rollup_merge.json' assert { type: 'json' }; import RootRollupJson from './target/rollup_root.json' assert { type: 'json' }; import { @@ -30,6 +35,7 @@ import { mapPrivateKernelInputsInitToNoir, mapPrivateKernelInputsInnerToNoir, mapPrivateKernelInputsOrderingToNoir, + mapPublicKernelInputs, mapRootRollupInputsToNoir, mapRootRollupPublicInputsFromNoir, } from './type_conversion.js'; @@ -39,6 +45,14 @@ import { ReturnType as FinalReturnType, InputType as OrderingInputType, } from './types/private_kernel_ordering_types.js'; +import { + InputType as PublicPrivatePreviousInputType, + ReturnType as PublicPrivatePreviousReturnType, +} from './types/public_kernel_private_previous_types.js'; +import { + InputType as PublicPublicPreviousInputType, + ReturnType as PublicPublicPreviousReturnType, +} from './types/public_kernel_public_previous_types.js'; import { InputType as MergeRollupInputType, ReturnType as MergeRollupReturnType } from './types/rollup_merge_types.js'; import { InputType as RootRollupInputType, ReturnType as RootRollupReturnType } from './types/rollup_root_types.js'; @@ -63,6 +77,10 @@ export const PrivateKernelInnerArtifact = PrivateKernelInnerJson as NoirCompiled export const PrivateKernelOrderingArtifact = PrivateKernelOrderingJson as NoirCompiledCircuit; +export const PublicKernelPrivatePreviousArtifact = PublicKernelPrivatePreviousJson as NoirCompiledCircuit; + +export const PublicKernelPublicPreviousArtifact = PublicKernelPublicPreviousJson as NoirCompiledCircuit; + /** * Executes the init private kernel. * @param privateKernelInputsInit - The private kernel inputs. @@ -123,6 +141,40 @@ export async function executeOrdering( return mapKernelCircuitPublicInputsFinalFromNoir(returnType); } +/** + * Executes the public kernel. + * @param privateKernelInputsInit - The public kernel private inputs. + * @returns The public inputs. + */ +export async function executePublicKernelPrivatePrevious( + publicKernelPrivateInputs: PublicKernelInputs, +): Promise { + const params: PublicPrivatePreviousInputType = { + input: mapPublicKernelInputs(publicKernelPrivateInputs), + }; + + const returnType = await executePublicKernelPrivatePreviousWithACVM(params); + + return mapKernelCircuitPublicInputsFromNoir(returnType); +} + +/** + * Executes the inner public kernel. + * @param privateKernelInputsInit - The public kernel private inputs. + * @returns The public inputs. + */ +export async function executePublicKernelPublicPrevious( + publicKernelPrivateInputs: PublicKernelInputs, +): Promise { + const params: PublicPrivatePreviousInputType = { + input: mapPublicKernelInputs(publicKernelPrivateInputs), + }; + + const returnType = await executePublicKernelPublicPreviousWithACVM(params); + + return mapKernelCircuitPublicInputsFromNoir(returnType); +} + /** * Executes the root rollup. * @param rootRollupInputs - The root rollup inputs. @@ -238,6 +290,55 @@ async function executePrivateKernelOrderingWithACVM(input: OrderingInputType): P return decodedInputs.return_value as FinalReturnType; } +/** + * Executes the public kernel with private prevoius kernel with the given inputs + */ +async function executePublicKernelPrivatePreviousWithACVM( + input: PublicPrivatePreviousInputType, +): Promise { + const initialWitnessMap = abiEncode(PublicKernelPrivatePreviousSimulatedJson.abi, input, null); + const decodedBytecode = Buffer.from(PublicKernelPrivatePreviousSimulatedJson.bytecode, 'base64'); + // Execute the circuit + const _witnessMap = await executeCircuitWithBlackBoxSolver( + await getSolver(), + decodedBytecode, + initialWitnessMap, + () => { + throw Error('unexpected oracle during execution'); + }, + ); + + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode(PublicKernelPrivatePreviousSimulatedJson.abi, _witnessMap); + // Cast the inputs as the return type + return decodedInputs.return_value as PublicPrivatePreviousReturnType; +} + +/** + * Executes the ordering private kernel with the given inputs using the acvm. + */ +async function executePublicKernelPublicPreviousWithACVM( + input: PublicPublicPreviousInputType, +): Promise { + const initialWitnessMap = abiEncode(PublicKernelPublicPreviousSimulatedJson.abi, input, null); + const decodedBytecode = Buffer.from(PublicKernelPublicPreviousSimulatedJson.bytecode, 'base64'); + // Execute the circuit + const _witnessMap = await executeCircuitWithBlackBoxSolver( + await getSolver(), + decodedBytecode, + initialWitnessMap, + () => { + throw Error('unexpected oracle during execution'); + }, + ); + + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode(PublicKernelPublicPreviousSimulatedJson.abi, _witnessMap); + + // Cast the inputs as the return type + return decodedInputs.return_value as PublicPublicPreviousReturnType; +} + /** * Executes the root rollup with the given inputs using the acvm. */ @@ -259,7 +360,6 @@ async function executeRootRollupWithACVM(input: RootRollupInputType): Promise, + contract_storage_update_requests: publicInputs.contractStorageUpdateRequests.map( + mapStorageUpdateRequestToNoir, + ) as FixedLengthArray, + contract_storage_reads: publicInputs.contractStorageReads.map(mapStorageReadToNoir) as FixedLengthArray< + StorageReadNoir, + 16 + >, + public_call_stack: publicInputs.publicCallStack.map(mapFieldToNoir) as FixedLengthArray, + new_commitments: publicInputs.newCommitments.map(mapFieldToNoir) as FixedLengthArray, + new_nullifiers: publicInputs.newNullifiers.map(mapFieldToNoir) as FixedLengthArray, + new_l2_to_l1_msgs: publicInputs.newL2ToL1Msgs.map(mapFieldToNoir) as FixedLengthArray, + unencrypted_logs_hash: publicInputs.unencryptedLogsHash.map(mapFieldToNoir) as FixedLengthArray, + unencrypted_log_preimages_length: mapFieldToNoir(publicInputs.unencryptedLogPreimagesLength), + historical_block_data: mapHistoricalBlockDataToNoir(publicInputs.historicBlockData), + + prover_address: mapAztecAddressToNoir(publicInputs.proverAddress), + }; +} /** * Maps a constant rollup data from noir to the circuits.js type. * @param constantRollupData - The noir constant rollup data. @@ -982,6 +1051,36 @@ export function mapBaseOrMergeRollupPublicInputsToNoir( }; } +/** + * Maps a public call stack item to noir. + * @param publicCallStackItem - The public call stack item. + * @returns The noir public call stack item. + */ +export function mapPublicCallStackItemToNoir(publicCallStackItem: PublicCallStackItem): PublicCallStackItemNoir { + return { + contract_address: mapAztecAddressToNoir(publicCallStackItem.contractAddress), + public_inputs: mapPublicCircuitPublicInputsToNoir(publicCallStackItem.publicInputs), + is_execution_request: publicCallStackItem.isExecutionRequest, + function_data: mapFunctionDataToNoir(publicCallStackItem.functionData), + }; +} + +/** + * Maps a public call data to noir. + * @param publicCall - The public call data. + * @returns The noir public call data. + */ +export function mapPublicCallDataToNoir(publicCall: PublicCallData): PublicCallDataNoir { + return { + call_stack_item: mapPublicCallStackItemToNoir(publicCall.callStackItem), + public_call_stack_preimages: publicCall.publicCallStackPreimages.map( + mapPublicCallStackItemToNoir, + ) as FixedLengthArray, + proof: {}, + portal_contract_address: mapEthAddressToNoir(EthAddress.fromField(publicCall.portalContractAddress)), + bytecode_hash: mapFieldToNoir(publicCall.bytecodeHash), + }; +} /** * Maps a base or merge rollup public inputs from noir to the circuits.js type. * @param baseOrMergeRollupPublicInputs - The noir base or merge rollup public inputs. @@ -1027,6 +1126,17 @@ export function mapPreviousRollupDataToNoir(previousRollupData: PreviousRollupDa }; } +/** + * Maps public kernel inputs to noir. + * @param inputs - The public kernel inputs. + * @returns The noir public kernel inputs. + */ +export function mapPublicKernelInputs(inputs: PublicKernelInputs): PublicKernelInputsNoir { + return { + previous_kernel: mapPreviousKernelDataToNoir(inputs.previousKernel), + public_call: mapPublicCallDataToNoir(inputs.publicCall), + }; +} /** * Maps a AOT snapshot to noir. * @param snapshot - The circuits.js AOT snapshot. diff --git a/yarn-project/noir-protocol-circuits/src/types/public_kernel_private_previous_types.ts b/yarn-project/noir-protocol-circuits/src/types/public_kernel_private_previous_types.ts new file mode 100644 index 00000000000..fce10410fa3 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/types/public_kernel_private_previous_types.ts @@ -0,0 +1,200 @@ +/* Autogenerated file, do not edit! */ + +/* eslint-disable */ + +export type FixedLengthArray = L extends 0 ? never[] : T[] & { length: L }; + +export type Field = string; +export type u32 = string; + +export interface AggregationObject {} + +export interface Address { + inner: Field; +} + +export interface EthAddress { + inner: Field; +} + +export interface NewContractData { + contract_address: Address; + portal_contract_address: EthAddress; + function_tree_root: Field; +} + +export interface FunctionSelector { + inner: u32; +} + +export interface FunctionData { + selector: FunctionSelector; + is_internal: boolean; + is_private: boolean; + is_constructor: boolean; +} + +export interface OptionallyRevealedData { + call_stack_item_hash: Field; + function_data: FunctionData; + vk_hash: Field; + portal_contract_address: EthAddress; + pay_fee_from_l1: boolean; + pay_fee_from_public_l2: boolean; + called_from_l1: boolean; + called_from_public_l2: boolean; +} + +export interface PublicDataUpdateRequest { + leaf_index: Field; + old_value: Field; + new_value: Field; +} + +export interface PublicDataRead { + leaf_index: Field; + value: Field; +} + +export interface CombinedAccumulatedData { + aggregation_object: AggregationObject; + read_requests: FixedLengthArray; + pending_read_requests: FixedLengthArray; + new_commitments: FixedLengthArray; + new_nullifiers: FixedLengthArray; + nullified_commitments: FixedLengthArray; + private_call_stack: FixedLengthArray; + public_call_stack: FixedLengthArray; + new_l2_to_l1_msgs: FixedLengthArray; + encrypted_logs_hash: FixedLengthArray; + unencrypted_logs_hash: FixedLengthArray; + encrypted_log_preimages_length: Field; + unencrypted_log_preimages_length: Field; + new_contracts: FixedLengthArray; + optionally_revealed_data: FixedLengthArray; + public_data_update_requests: FixedLengthArray; + public_data_reads: FixedLengthArray; +} + +export interface Block { + note_hash_tree_root: Field; + nullifier_tree_root: Field; + contract_tree_root: Field; + l1_to_l2_data_tree_root: Field; + public_data_tree_root: Field; + global_variables_hash: Field; +} + +export interface HistoricalBlockData { + blocks_tree_root: Field; + block: Block; + private_kernel_vk_tree_root: Field; +} + +export interface Point { + x: Field; + y: Field; +} + +export interface ContractDeploymentData { + deployer_public_key: Point; + constructor_vk_hash: Field; + function_tree_root: Field; + contract_address_salt: Field; + portal_contract_address: EthAddress; +} + +export interface TxContext { + is_fee_payment_tx: boolean; + is_rebate_payment_tx: boolean; + is_contract_deployment_tx: boolean; + contract_deployment_data: ContractDeploymentData; + chain_id: Field; + version: Field; +} + +export interface CombinedConstantData { + block_data: HistoricalBlockData; + tx_context: TxContext; +} + +export interface KernelCircuitPublicInputs { + end: CombinedAccumulatedData; + constants: CombinedConstantData; + is_private: boolean; +} + +export interface Proof {} + +export interface VerificationKey {} + +export interface PreviousKernelData { + public_inputs: KernelCircuitPublicInputs; + proof: Proof; + vk: VerificationKey; + vk_index: u32; + vk_path: FixedLengthArray; +} + +export interface CallContext { + msg_sender: Address; + storage_contract_address: Address; + portal_contract_address: EthAddress; + function_selector: FunctionSelector; + is_delegate_call: boolean; + is_static_call: boolean; + is_contract_deployment: boolean; +} + +export interface StorageUpdateRequest { + storage_slot: Field; + old_value: Field; + new_value: Field; +} + +export interface StorageRead { + storage_slot: Field; + current_value: Field; +} + +export interface PublicCircuitPublicInputs { + call_context: CallContext; + args_hash: Field; + return_values: FixedLengthArray; + contract_storage_update_requests: FixedLengthArray; + contract_storage_reads: FixedLengthArray; + public_call_stack: FixedLengthArray; + new_commitments: FixedLengthArray; + new_nullifiers: FixedLengthArray; + new_l2_to_l1_msgs: FixedLengthArray; + unencrypted_logs_hash: FixedLengthArray; + unencrypted_log_preimages_length: Field; + historical_block_data: HistoricalBlockData; + prover_address: Address; +} + +export interface PublicCallStackItem { + contract_address: Address; + public_inputs: PublicCircuitPublicInputs; + function_data: FunctionData; + is_execution_request: boolean; +} + +export interface PublicCallData { + call_stack_item: PublicCallStackItem; + public_call_stack_preimages: FixedLengthArray; + proof: Proof; + portal_contract_address: EthAddress; + bytecode_hash: Field; +} + +export interface PublicKernelPrivatePreviousInputs { + previous_kernel: PreviousKernelData; + public_call: PublicCallData; +} + +export type ReturnType = KernelCircuitPublicInputs; + +export interface InputType { + input: PublicKernelPrivatePreviousInputs; +} diff --git a/yarn-project/noir-protocol-circuits/src/types/public_kernel_public_previous_types.ts b/yarn-project/noir-protocol-circuits/src/types/public_kernel_public_previous_types.ts new file mode 100644 index 00000000000..55e4e40a87e --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/types/public_kernel_public_previous_types.ts @@ -0,0 +1,200 @@ +/* Autogenerated file, do not edit! */ + +/* eslint-disable */ + +export type FixedLengthArray = L extends 0 ? never[] : T[] & { length: L }; + +export type Field = string; +export type u32 = string; + +export interface AggregationObject {} + +export interface Address { + inner: Field; +} + +export interface EthAddress { + inner: Field; +} + +export interface NewContractData { + contract_address: Address; + portal_contract_address: EthAddress; + function_tree_root: Field; +} + +export interface FunctionSelector { + inner: u32; +} + +export interface FunctionData { + selector: FunctionSelector; + is_internal: boolean; + is_private: boolean; + is_constructor: boolean; +} + +export interface OptionallyRevealedData { + call_stack_item_hash: Field; + function_data: FunctionData; + vk_hash: Field; + portal_contract_address: EthAddress; + pay_fee_from_l1: boolean; + pay_fee_from_public_l2: boolean; + called_from_l1: boolean; + called_from_public_l2: boolean; +} + +export interface PublicDataUpdateRequest { + leaf_index: Field; + old_value: Field; + new_value: Field; +} + +export interface PublicDataRead { + leaf_index: Field; + value: Field; +} + +export interface CombinedAccumulatedData { + aggregation_object: AggregationObject; + read_requests: FixedLengthArray; + pending_read_requests: FixedLengthArray; + new_commitments: FixedLengthArray; + new_nullifiers: FixedLengthArray; + nullified_commitments: FixedLengthArray; + private_call_stack: FixedLengthArray; + public_call_stack: FixedLengthArray; + new_l2_to_l1_msgs: FixedLengthArray; + encrypted_logs_hash: FixedLengthArray; + unencrypted_logs_hash: FixedLengthArray; + encrypted_log_preimages_length: Field; + unencrypted_log_preimages_length: Field; + new_contracts: FixedLengthArray; + optionally_revealed_data: FixedLengthArray; + public_data_update_requests: FixedLengthArray; + public_data_reads: FixedLengthArray; +} + +export interface Block { + note_hash_tree_root: Field; + nullifier_tree_root: Field; + contract_tree_root: Field; + l1_to_l2_data_tree_root: Field; + public_data_tree_root: Field; + global_variables_hash: Field; +} + +export interface HistoricalBlockData { + blocks_tree_root: Field; + block: Block; + private_kernel_vk_tree_root: Field; +} + +export interface Point { + x: Field; + y: Field; +} + +export interface ContractDeploymentData { + deployer_public_key: Point; + constructor_vk_hash: Field; + function_tree_root: Field; + contract_address_salt: Field; + portal_contract_address: EthAddress; +} + +export interface TxContext { + is_fee_payment_tx: boolean; + is_rebate_payment_tx: boolean; + is_contract_deployment_tx: boolean; + contract_deployment_data: ContractDeploymentData; + chain_id: Field; + version: Field; +} + +export interface CombinedConstantData { + block_data: HistoricalBlockData; + tx_context: TxContext; +} + +export interface KernelCircuitPublicInputs { + end: CombinedAccumulatedData; + constants: CombinedConstantData; + is_private: boolean; +} + +export interface Proof {} + +export interface VerificationKey {} + +export interface PreviousKernelData { + public_inputs: KernelCircuitPublicInputs; + proof: Proof; + vk: VerificationKey; + vk_index: u32; + vk_path: FixedLengthArray; +} + +export interface CallContext { + msg_sender: Address; + storage_contract_address: Address; + portal_contract_address: EthAddress; + function_selector: FunctionSelector; + is_delegate_call: boolean; + is_static_call: boolean; + is_contract_deployment: boolean; +} + +export interface StorageUpdateRequest { + storage_slot: Field; + old_value: Field; + new_value: Field; +} + +export interface StorageRead { + storage_slot: Field; + current_value: Field; +} + +export interface PublicCircuitPublicInputs { + call_context: CallContext; + args_hash: Field; + return_values: FixedLengthArray; + contract_storage_update_requests: FixedLengthArray; + contract_storage_reads: FixedLengthArray; + public_call_stack: FixedLengthArray; + new_commitments: FixedLengthArray; + new_nullifiers: FixedLengthArray; + new_l2_to_l1_msgs: FixedLengthArray; + unencrypted_logs_hash: FixedLengthArray; + unencrypted_log_preimages_length: Field; + historical_block_data: HistoricalBlockData; + prover_address: Address; +} + +export interface PublicCallStackItem { + contract_address: Address; + public_inputs: PublicCircuitPublicInputs; + function_data: FunctionData; + is_execution_request: boolean; +} + +export interface PublicCallData { + call_stack_item: PublicCallStackItem; + public_call_stack_preimages: FixedLengthArray; + proof: Proof; + portal_contract_address: EthAddress; + bytecode_hash: Field; +} + +export interface PublicKernelPublicPreviousInputs { + previous_kernel: PreviousKernelData; + public_call: PublicCallData; +} + +export type ReturnType = KernelCircuitPublicInputs; + +export interface InputType { + input: PublicKernelPublicPreviousInputs; +} diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.ts index 501cd78ca4b..cfdb541af78 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.ts @@ -38,7 +38,7 @@ import { VK_TREE_HEIGHT, } from '@aztec/circuits.js'; import { computeCallStackItemHash, computeVarArgsHash } from '@aztec/circuits.js/abis'; -import { arrayNonEmptyLength, isArrayEmpty, padArrayEnd, padArrayStart } from '@aztec/foundation/collection'; +import { arrayNonEmptyLength, isArrayEmpty, padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { Tuple, mapTuple, to2Fields } from '@aztec/foundation/serialize'; import { ContractDataSource, FunctionL2Logs, L1ToL2MessageSource, MerkleTreeId, Tx } from '@aztec/types'; @@ -302,8 +302,8 @@ export class PublicProcessor { ); } - // Top of the stack is at the end of the array, so we padStart - return padArrayStart(preimages, PublicCallStackItem.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); + // note this was previously padArrayStart in the cpp kernel, logic was updated in noir translation + return padArrayEnd(preimages, PublicCallStackItem.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); } protected getBytecodeHash(_result: PublicExecutionResult) { diff --git a/yarn-project/sequencer-client/src/simulator/public_kernel.ts b/yarn-project/sequencer-client/src/simulator/public_kernel.ts index 89df560bcc3..482d7e61446 100644 --- a/yarn-project/sequencer-client/src/simulator/public_kernel.ts +++ b/yarn-project/sequencer-client/src/simulator/public_kernel.ts @@ -1,6 +1,7 @@ -import { PublicKernelInputs, PublicKernelPublicInputs, simulatePublicKernelCircuit } from '@aztec/circuits.js'; +import { PublicKernelInputs, PublicKernelPublicInputs } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { elapsed } from '@aztec/foundation/timer'; +import { executePublicKernelPrivatePrevious, executePublicKernelPublicPrevious } from '@aztec/noir-protocol-circuits'; import { CircuitSimulationStats } from '@aztec/types/stats'; import { PublicKernelCircuitSimulator } from './index.js'; @@ -18,7 +19,7 @@ export class WasmPublicKernelCircuitSimulator implements PublicKernelCircuitSimu */ public async publicKernelCircuitPrivateInput(input: PublicKernelInputs): Promise { if (!input.previousKernel.publicInputs.isPrivate) throw new Error(`Expected private kernel previous inputs`); - const [duration, result] = await elapsed(() => simulatePublicKernelCircuit(input)); + const [duration, result] = await elapsed(() => executePublicKernelPrivatePrevious(input)); this.log(`Simulated public kernel circuit with private input`, { eventName: 'circuit-simulation', circuitName: 'public-kernel-private-input', @@ -36,7 +37,7 @@ export class WasmPublicKernelCircuitSimulator implements PublicKernelCircuitSimu */ public async publicKernelCircuitNonFirstIteration(input: PublicKernelInputs): Promise { if (input.previousKernel.publicInputs.isPrivate) throw new Error(`Expected public kernel previous inputs`); - const [duration, result] = await elapsed(() => simulatePublicKernelCircuit(input)); + const [duration, result] = await elapsed(() => executePublicKernelPublicPrevious(input)); this.log(`Simulated public kernel circuit non-first iteration`, { eventName: 'circuit-simulation', circuitName: 'public-kernel-non-first-iteration',