diff --git a/noir-projects/Dockerfile b/noir-projects/Dockerfile index 574738e2a1b..ab4c6270e97 100644 --- a/noir-projects/Dockerfile +++ b/noir-projects/Dockerfile @@ -2,7 +2,8 @@ FROM aztecprotocol/noir as noir FROM aztecprotocol/avm-transpiler as transpiler FROM ubuntu:lunar AS builder -RUN apt-get update && apt-get install -y parallel +RUN apt-get update && apt-get install -y parallel nodejs npm +RUN npm install --global yarn # Copy in nargo COPY --from=noir /usr/src/noir/noir-repo/target/release/nargo /usr/src/noir/noir-repo/target/release/nargo ENV PATH="/usr/src/noir/noir-repo/target/release:${PATH}" diff --git a/noir-projects/noir-protocol-circuits/.gitignore b/noir-projects/noir-protocol-circuits/.gitignore index b8a74c10108..9ff1b82cda5 100644 --- a/noir-projects/noir-protocol-circuits/.gitignore +++ b/noir-projects/noir-protocol-circuits/.gitignore @@ -1,3 +1,5 @@ Prover.toml Verifier.toml target +crates/autogenerated +Nargo.toml \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/Nargo.toml b/noir-projects/noir-protocol-circuits/Nargo.template.toml similarity index 100% rename from noir-projects/noir-protocol-circuits/Nargo.toml rename to noir-projects/noir-protocol-circuits/Nargo.template.toml diff --git a/noir-projects/noir-protocol-circuits/bootstrap.sh b/noir-projects/noir-protocol-circuits/bootstrap.sh index e647f07b80f..735ac9e1982 100755 --- a/noir-projects/noir-protocol-circuits/bootstrap.sh +++ b/noir-projects/noir-protocol-circuits/bootstrap.sh @@ -15,6 +15,9 @@ if [ -n "$CMD" ]; then fi fi +yarn +node ./index.js + echo "Compiling protocol circuits..." NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} $NARGO compile --silence-warnings \ No newline at end of file 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 db96da72dbb..d43ae5e907d 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 @@ -1,7 +1,7 @@ use crate::private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer; use dep::reset_kernel_lib::{ NoteHashReadRequestHints, NullifierReadRequestHints, PrivateValidationRequestProcessor, - verify_squashed_transient_note_hashes_and_nullifiers + verify_squashed_transient_note_hashes_and_nullifiers, reset::nullifier_key::NullifierKeyHint }; use dep::types::{ abis::{ @@ -25,22 +25,22 @@ struct PrivateKernelResetOutputs { note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], } -struct PrivateKernelResetHints { +struct PrivateKernelResetHints { transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - note_hash_read_request_hints: NoteHashReadRequestHints, - nullifier_read_request_hints: NullifierReadRequestHints, - master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], + note_hash_read_request_hints: NoteHashReadRequestHints, + nullifier_read_request_hints: NullifierReadRequestHints, + master_nullifier_secret_keys: [NullifierKeyHint; NLL_KEYS], } -struct PrivateKernelResetCircuitPrivateInputs { +struct PrivateKernelResetCircuitPrivateInputs { previous_kernel: PrivateKernelData, outputs: PrivateKernelResetOutputs, - hints: PrivateKernelResetHints, + hints: PrivateKernelResetHints, } -impl PrivateKernelResetCircuitPrivateInputs { +impl PrivateKernelResetCircuitPrivateInputs { pub fn execute(self) -> PrivateKernelCircuitPublicInputs { let mut previous_public_inputs = self.previous_kernel.public_inputs; @@ -86,7 +86,8 @@ mod tests { nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} }, - reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} + reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus}, + reset::nullifier_key::NullifierKeyHint }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -178,7 +179,7 @@ mod tests { transient_note_hash_indexes_for_logs: self.transient_note_hash_indexes_for_logs, note_hash_read_request_hints: self.note_hash_read_request_hints_builder.to_hints(), nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), - master_nullifier_secret_keys: [GrumpkinPrivateKey::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX] + master_nullifier_secret_keys: [NullifierKeyHint::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX] }; let kernel = PrivateKernelResetCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), outputs, hints }; 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 3c887b05361..b35cb1e6d86 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 @@ -92,11 +92,6 @@ mod tests { // TODO: Reduce the duplicated code/tests for PrivateKernelTailInputs and PrivateKernelTailToPublicInputs. struct PrivateKernelTailInputsBuilder { previous_kernel: FixtureBuilder, - transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder, - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } impl PrivateKernelTailInputsBuilder { @@ -106,14 +101,7 @@ mod tests { previous_kernel.append_new_nullifiers(1); - PrivateKernelTailInputsBuilder { - previous_kernel, - transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) - } + PrivateKernelTailInputsBuilder { previous_kernel } } // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed @@ -177,24 +165,6 @@ mod tests { let sorted_unencrypted_log_hashes = sorted.sorted_array; let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; - let mut sorted_transient_nullifier_indexes_for_note_hashes = [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX]; - for i in 0..self.transient_nullifier_indexes_for_note_hashes.len() { - let old_index = self.transient_nullifier_indexes_for_note_hashes[i]; - if old_index != MAX_NEW_NULLIFIERS_PER_TX { - let new_note_hash_index = sorted_new_note_hashes_indexes[i]; - sorted_transient_nullifier_indexes_for_note_hashes[new_note_hash_index] = sorted_new_nullifiers_indexes[old_index]; - } - } - - let mut sorted_transient_note_hash_indexes_for_nullifiers = [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX]; - for i in 0..self.transient_note_hash_indexes_for_nullifiers.len() { - let old_index = self.transient_note_hash_indexes_for_nullifiers[i]; - if old_index != MAX_NEW_NOTE_HASHES_PER_TX { - let new_nullifier_index = sorted_new_nullifiers_indexes[i]; - sorted_transient_note_hash_indexes_for_nullifiers[new_nullifier_index] = sorted_new_note_hashes_indexes[old_index]; - } - } - let hints = PrivateKernelTailHints { sorted_new_note_hashes, sorted_new_note_hashes_indexes, 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 a50185244a1..8e8993d4bb2 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 @@ -89,11 +89,6 @@ mod tests { // TODO: Reduce the duplicated code/tests for PrivateKernelTailToPublicInputs and PrivateKernelTailInputs. struct PrivateKernelTailToPublicInputsBuilder { previous_kernel: FixtureBuilder, - transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder, - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } impl PrivateKernelTailToPublicInputsBuilder { @@ -103,14 +98,7 @@ mod tests { previous_kernel.append_new_nullifiers(1); previous_kernel.push_public_call_request(1, false); - PrivateKernelTailToPublicInputsBuilder { - previous_kernel, - transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) - } + PrivateKernelTailToPublicInputsBuilder { previous_kernel } } // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-reset-simulated/src/main.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-reset-simulated/src/main.nr index 36b736b9ea7..2d4947cfcef 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-reset-simulated/src/main.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-reset-simulated/src/main.nr @@ -1,6 +1,18 @@ use dep::private_kernel_lib::PrivateKernelResetCircuitPrivateInputs; -use dep::types::PrivateKernelCircuitPublicInputs; +use dep::types::{ + PrivateKernelCircuitPublicInputs, + constants::{ + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX +} +}; + +global NOTE_HASH_PENDING_AMOUNT = MAX_NOTE_HASH_READ_REQUESTS_PER_TX; // 128 +global NOTE_HASH_SETTLED_AMOUNT = MAX_NOTE_HASH_READ_REQUESTS_PER_TX; +global NULLIFIER_PENDING_AMOUNT = MAX_NULLIFIER_READ_REQUESTS_PER_TX; // 8 +global NULLIFIER_SETTLED_AMOUNT = MAX_NULLIFIER_READ_REQUESTS_PER_TX; +global NULLIFIER_KEYS = MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX; // 4 -unconstrained fn main(input: PrivateKernelResetCircuitPrivateInputs) -> pub PrivateKernelCircuitPublicInputs { +unconstrained fn main(input: PrivateKernelResetCircuitPrivateInputs) -> pub PrivateKernelCircuitPublicInputs { input.execute() } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-reset/src/main.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-reset/src/main.nr index fddb8407810..d39fcc38ecf 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-reset/src/main.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-reset/src/main.nr @@ -1,7 +1,19 @@ use dep::private_kernel_lib::PrivateKernelResetCircuitPrivateInputs; -use dep::types::PrivateKernelCircuitPublicInputs; +use dep::types::{ + PrivateKernelCircuitPublicInputs, + constants::{ + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX +} +}; + +global NOTE_HASH_PENDING_AMOUNT = MAX_NOTE_HASH_READ_REQUESTS_PER_TX; // 128 +global NOTE_HASH_SETTLED_AMOUNT = MAX_NOTE_HASH_READ_REQUESTS_PER_TX; +global NULLIFIER_PENDING_AMOUNT = MAX_NULLIFIER_READ_REQUESTS_PER_TX; // 8 +global NULLIFIER_SETTLED_AMOUNT = MAX_NULLIFIER_READ_REQUESTS_PER_TX; +global NULLIFIER_KEYS = MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX; // 4 #[recursive] -fn main(input: PrivateKernelResetCircuitPrivateInputs) -> pub PrivateKernelCircuitPublicInputs { +fn main(input: PrivateKernelResetCircuitPrivateInputs) -> pub PrivateKernelCircuitPublicInputs { input.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 632555d5307..a7c0da2114f 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 @@ -8,14 +8,14 @@ use dep::types::{ accumulated_data::CombinedAccumulatedData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData }, - constants::MAX_PUBLIC_DATA_HINTS, + constants::{MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, merkle_tree::{conditionally_assert_check_membership, MembershipWitness}, partial_state_reference::PartialStateReference, utils::{arrays::array_length} }; struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, - nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_read_request_hints: NullifierReadRequestHints, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], public_data_read_request_hints: PublicDataReadRequestHints, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr index cb105f6543c..073cdfd825d 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr @@ -36,10 +36,10 @@ impl SettledReadHint for NoteHashSe } } -struct NoteHashReadRequestHints { +struct NoteHashReadRequestHints { read_request_statuses: [ReadRequestStatus; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - pending_read_hints: [PendingReadHint; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - settled_read_hints: [NoteHashSettledReadHint; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + pending_read_hints: [PendingReadHint; PENDING], + settled_read_hints: [NoteHashSettledReadHint; SETTLED], } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr index e7363f828c4..48f81f127e6 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr @@ -36,10 +36,10 @@ impl SettledReadHint for Nullifier } } -struct NullifierReadRequestHints { +struct NullifierReadRequestHints { read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - pending_read_hints: [PendingReadHint; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - settled_read_hints: [NullifierSettledReadHint; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pending_read_hints: [PendingReadHint; PENDING], + settled_read_hints: [NullifierSettledReadHint; SETTLED], } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index d8516c91ae2..877112c0dd1 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -1,6 +1,7 @@ use crate::{ note_hash_read_request_reset::NoteHashReadRequestHints, - nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests + nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests, + reset::nullifier_key::{NullifierKeyHint, reset_nullifier_keys} }; use dep::types::{ abis::{ @@ -16,18 +17,18 @@ use dep::types::{ utils::arrays::filter_array_to_bounded_vec }; -struct PrivateValidationRequestProcessor { +struct PrivateValidationRequestProcessor { validation_requests: ValidationRequests, - note_hash_read_request_hints: NoteHashReadRequestHints, + note_hash_read_request_hints: NoteHashReadRequestHints, pending_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, - nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_read_request_hints: NullifierReadRequestHints, pending_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], nullifier_tree_root: Field, - master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], + master_nullifier_secret_keys: [NullifierKeyHint; NLL_KEYS], } -impl PrivateValidationRequestProcessor { +impl PrivateValidationRequestProcessor { pub fn validate(self) -> ValidationRequests { let remaining_note_hash_read_requests = self.validate_note_hash_read_requests(); let remaining_nullifier_read_requests = self.validate_nullifier_read_requests(); @@ -66,36 +67,9 @@ impl PrivateValidationRequestProcessor { } fn validate_nullifier_keys(self) -> BoundedVec { - let mut should_propagate = [false; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX]; - let requests = self.validation_requests.nullifier_key_validation_requests; - for i in 0..MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX { - let request = requests[i].request; - if !is_empty(request) { - let contract_address = requests[i].contract_address; - let master_nullifier_secret_key = self.master_nullifier_secret_keys[i]; - if !is_empty(master_nullifier_secret_key) { - // First we check that derived public key matches master nullifier public key from request - let master_nullifier_public_key = master_nullifier_secret_key.derive_public_key(); - assert( - master_nullifier_public_key.eq(request.master_nullifier_public_key), "Failed to derive matching master nullifier public key from the secret key." - ); - - // Then we check that siloing the master secret key with the contract address gives the app nullifier secret key - - let app_nullifier_secret_key = poseidon2_hash( - [ - master_nullifier_secret_key.high, master_nullifier_secret_key.low, contract_address.to_field(), GENERATOR_INDEX__NSK_M - ] - ); - assert( - app_nullifier_secret_key.eq(request.app_nullifier_secret_key), "Failed to derive matching app nullifier secret key from the secret key." - ); - } else { - should_propagate[i] = true; - } - } - } - - filter_array_to_bounded_vec(requests, should_propagate) + reset_nullifier_keys( + self.validation_requests.nullifier_key_validation_requests, + self.master_nullifier_secret_keys + ) } } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr index a25b760e1d4..787a8ebc630 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr @@ -12,7 +12,7 @@ use dep::types::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, validation_requests::ValidationRequests }, - constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX}, + constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, hash::silo_nullifier, traits::is_empty, utils::arrays::{array_merge, array_to_bounded_vec, assert_sorted_array} }; @@ -21,7 +21,7 @@ struct PublicValidationRequestProcessor { validation_requests: ValidationRequests, pending_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], pending_public_data_writes: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_read_request_hints: NullifierReadRequestHints, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, nullifier_tree_root: Field, public_data_read_request_hints: PublicDataReadRequestHints, @@ -31,7 +31,7 @@ struct PublicValidationRequestProcessor { impl PublicValidationRequestProcessor { pub fn new( public_inputs: PublicKernelCircuitPublicInputs, - nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_read_request_hints: NullifierReadRequestHints, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, nullifier_tree_root: Field, public_data_read_request_hints: PublicDataReadRequestHints, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr index 92b72993869..740cbc359fb 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr @@ -2,3 +2,4 @@ mod mutable_data_read_request; mod non_existent_read_request; mod read_request; mod transient_data; +mod nullifier_key; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/nullifier_key.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/nullifier_key.nr new file mode 100644 index 00000000000..91207ddb717 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/nullifier_key.nr @@ -0,0 +1,66 @@ +use crate::{nullifier_read_request_reset::NullifierReadRequestHints}; +use dep::types::{ + traits::{Empty, is_empty}, + abis::{nullifier_key_validation_request::ScopedNullifierKeyValidationRequest}, + constants::{MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M}, + grumpkin_private_key::GrumpkinPrivateKey, hash::poseidon2_hash, + utils::arrays::filter_array_to_bounded_vec +}; + +struct NullifierKeyHint { + private_key: GrumpkinPrivateKey, + request_index: u64, +} + +impl Empty for NullifierKeyHint { + fn empty() -> Self { + NullifierKeyHint { + private_key: GrumpkinPrivateKey::empty(), + request_index: 0, + } + } +} + +impl Eq for NullifierKeyHint { + fn eq(self, other: Self) -> bool { + self.private_key.eq(other.private_key) & self.request_index.eq(other.request_index) + } + +} + +pub fn reset_nullifier_keys( + nullifier_key_validation_requests: [ScopedNullifierKeyValidationRequest; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], + key_hints: [NullifierKeyHint; N] +) -> BoundedVec { + let mut should_propagate = nullifier_key_validation_requests.map(|req| !is_empty(req)); + for i in 0..N { + let hint = key_hints[i]; + if !is_empty(hint) { + let scoped_request = nullifier_key_validation_requests[hint.request_index]; + let contract_address = scoped_request.contract_address; + let request = scoped_request.request; + let master_nullifier_secret_key = hint.private_key; + + // First we check that derived public key matches master nullifier public key from request + let master_nullifier_public_key = master_nullifier_secret_key.derive_public_key(); + assert( + master_nullifier_public_key.eq(request.master_nullifier_public_key), "Failed to derive matching master nullifier public key from the secret key." + ); + + // Then we check that siloing the master secret key with the contract address gives the app nullifier secret key + + let app_nullifier_secret_key = poseidon2_hash( + [ + master_nullifier_secret_key.high, master_nullifier_secret_key.low, contract_address.to_field(), GENERATOR_INDEX__NSK_M + ] + ); + assert( + app_nullifier_secret_key.eq(request.app_nullifier_secret_key), "Failed to derive matching app nullifier secret key from the secret key." + ); + + should_propagate[hint.request_index] = false; + } + } + + filter_array_to_bounded_vec(nullifier_key_validation_requests, should_propagate) +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index 4153aff1344..72862ea7ff6 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -22,7 +22,7 @@ impl NoteHashReadRequestHintsBuilder { } } - pub fn to_hints(self) -> NoteHashReadRequestHints { + pub fn to_hints(self) -> NoteHashReadRequestHints { NoteHashReadRequestHints { read_request_statuses: self.read_request_statuses, pending_read_hints: self.pending_read_hints.storage, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index d9640b2ee09..46142a29a38 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -22,7 +22,7 @@ impl NullifierReadRequestHintsBuilder { } } - pub fn to_hints(self) -> NullifierReadRequestHints { + pub fn to_hints(self) -> NullifierReadRequestHints { NullifierReadRequestHints { read_request_statuses: self.read_request_statuses, pending_read_hints: self.pending_read_hints.storage, diff --git a/noir-projects/noir-protocol-circuits/index.js b/noir-projects/noir-protocol-circuits/index.js new file mode 100644 index 00000000000..a57793eae85 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/index.js @@ -0,0 +1,82 @@ +const TOML = require("@iarna/toml"); +const fs = require("fs"); +const path = require("path"); + +const nargoTomlTemplate = TOML.parse( + fs.readFileSync("./Nargo.template.toml", "utf8") +); +const autogeneratedCircuitsPath = path.join(__dirname, "crates/autogenerated"); + +if (fs.existsSync(autogeneratedCircuitsPath)) { + fs.rmSync(autogeneratedCircuitsPath, { recursive: true }); +} +fs.mkdirSync(autogeneratedCircuitsPath); + +function generateResetVariants() { + const resetVariants = require("./reset_variants.json"); + + generateVariants("private-kernel-reset", resetVariants); + generateVariants("private-kernel-reset-simulated", resetVariants); +} + +function generateVariants(originalFolder, variantsArray) { + const originalCrateFolder = path.join(__dirname, "crates", originalFolder); + const originalNargoToml = TOML.parse( + fs.readFileSync(path.join(originalCrateFolder, "Nargo.toml"), "utf8") + ); + const originalName = originalNargoToml.package.name; + + for ({ tag, replacements } of variantsArray) { + const variantFolder = `${originalFolder}-${tag}`; + const variantNargoToml = structuredClone(originalNargoToml); + for ([depName, depDescriptor] of Object.entries( + variantNargoToml.dependencies + )) { + if (depDescriptor.path) { + depDescriptor.path = "../" + depDescriptor.path; + } + } + variantNargoToml.package.name = `${originalName}_${tag}`; + + let mainDotNoirCode = fs.readFileSync( + path.join(originalCrateFolder, "src/main.nr"), + "utf8" + ); + + for ([variableName, variableValue] of Object.entries(replacements)) { + mainDotNoirCode = mainDotNoirCode.replace( + new RegExp(`^global\\s+${variableName}\\s=\\s.*;.*$`, "m"), + `global ${variableName} = ${variableValue};` + ); + } + + fs.mkdirSync(path.join(autogeneratedCircuitsPath, variantFolder, "src"), { + recursive: true, + }); + + fs.writeFileSync( + path.join(autogeneratedCircuitsPath, variantFolder, "src/main.nr"), + mainDotNoirCode + ); + + fs.writeFileSync( + path.join(autogeneratedCircuitsPath, variantFolder, "Nargo.toml"), + TOML.stringify(variantNargoToml) + ); + } +} + +generateResetVariants(); + +for (entry of fs.readdirSync(autogeneratedCircuitsPath)) { + nargoTomlTemplate.workspace.members.push( + path.relative(__dirname, path.join(autogeneratedCircuitsPath, entry)) + ); +} + +fs.writeFileSync( + "./Nargo.toml", + `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n${TOML.stringify( + nargoTomlTemplate + )}` +); diff --git a/noir-projects/noir-protocol-circuits/package.json b/noir-projects/noir-protocol-circuits/package.json new file mode 100644 index 00000000000..5e0598e8ce7 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/package.json @@ -0,0 +1,8 @@ +{ + "name": "noir-protocol-circuits-generator", + "version": "0.0.0", + "main": "index.js", + "dependencies": { + "@iarna/toml": "^2.2.5" + } +} \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/reset_variants.json b/noir-projects/noir-protocol-circuits/reset_variants.json new file mode 100644 index 00000000000..d241396dece --- /dev/null +++ b/noir-projects/noir-protocol-circuits/reset_variants.json @@ -0,0 +1,35 @@ +[ + { + "tag": "big", + "priority": 98, + "replacements": { + "NOTE_HASH_PENDING_AMOUNT": 64, + "NOTE_HASH_SETTLED_AMOUNT": 64, + "NULLIFIER_PENDING_AMOUNT": 64, + "NULLIFIER_SETTLED_AMOUNT": 64, + "NULLIFIER_KEYS": 4 + } + }, + { + "tag": "medium", + "priority": 99, + "replacements": { + "NOTE_HASH_PENDING_AMOUNT": 32, + "NOTE_HASH_SETTLED_AMOUNT": 32, + "NULLIFIER_PENDING_AMOUNT": 32, + "NULLIFIER_SETTLED_AMOUNT": 32, + "NULLIFIER_KEYS": 4 + } + }, + { + "tag": "small", + "priority": 100, + "replacements": { + "NOTE_HASH_PENDING_AMOUNT": 16, + "NOTE_HASH_SETTLED_AMOUNT": 16, + "NULLIFIER_PENDING_AMOUNT": 16, + "NULLIFIER_SETTLED_AMOUNT": 16, + "NULLIFIER_KEYS": 2 + } + } +] \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/yarn.lock b/noir-projects/noir-protocol-circuits/yarn.lock new file mode 100644 index 00000000000..f411a21e2d6 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@iarna/toml@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index 7c86855f16a..e92d481c252 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -18,6 +18,7 @@ aztec-node/data* aztec-js/src/account_contract/artifacts aztec/log circuits.js/fixtures/*.json +circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs_variants.ts docs/dist end-to-end/addresses.json end-to-end/log diff --git a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts index 5e76f59f489..5b904dd4a68 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts +++ b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts @@ -7,7 +7,7 @@ import { type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, type PrivateKernelInnerCircuitPrivateInputs, - type PrivateKernelResetCircuitPrivateInputs, + type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, Proof, @@ -24,6 +24,7 @@ import { Timer } from '@aztec/foundation/timer'; import { ClientCircuitArtifacts, type ClientProtocolArtifact, + PrivateResetTagToArtifactName, convertPrivateKernelInitInputsToWitnessMap, convertPrivateKernelInitOutputsFromWitnessMap, convertPrivateKernelInnerInputsToWitnessMap, @@ -110,13 +111,13 @@ export class BBNativeProofCreator implements ProofCreator { } public async createProofReset( - inputs: PrivateKernelResetCircuitPrivateInputs, + inputs: PrivateKernelResetCircuitPrivateInputsVariants, ): Promise> { return await this.createSafeProof( inputs, - 'PrivateKernelResetArtifact', + PrivateResetTagToArtifactName[inputs.sizeTag], convertPrivateKernelResetInputsToWitnessMap, - convertPrivateKernelResetOutputsFromWitnessMap, + output => convertPrivateKernelResetOutputsFromWitnessMap(output, inputs.sizeTag), ); } diff --git a/yarn-project/bb-prover/src/stats.ts b/yarn-project/bb-prover/src/stats.ts index 9627d0db8f9..ad52f26d869 100644 --- a/yarn-project/bb-prover/src/stats.ts +++ b/yarn-project/bb-prover/src/stats.ts @@ -47,8 +47,14 @@ export function mapProtocolArtifactNameToCircuitName( return 'private-kernel-tail'; case 'PrivateKernelTailToPublicArtifact': return 'private-kernel-tail-to-public'; - case 'PrivateKernelResetArtifact': - return 'private-kernel-reset'; + case 'PrivateKernelResetFullArtifact': + return 'private-kernel-reset-full'; + case 'PrivateKernelResetBigArtifact': + return 'private-kernel-reset-big'; + case 'PrivateKernelResetMediumArtifact': + return 'private-kernel-reset-medium'; + case 'PrivateKernelResetSmallArtifact': + return 'private-kernel-reset-small'; default: throw new Error(`Unknown circuit type: ${artifact}`); } diff --git a/yarn-project/circuit-types/src/interfaces/proof_creator.ts b/yarn-project/circuit-types/src/interfaces/proof_creator.ts index 7a3ef4042dc..82c57b993c2 100644 --- a/yarn-project/circuit-types/src/interfaces/proof_creator.ts +++ b/yarn-project/circuit-types/src/interfaces/proof_creator.ts @@ -4,7 +4,7 @@ import { type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, type PrivateKernelInnerCircuitPrivateInputs, - type PrivateKernelResetCircuitPrivateInputs, + type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, type RECURSIVE_PROOF_LENGTH, @@ -85,7 +85,7 @@ export interface ProofCreator { * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ createProofReset( - privateKernelInputsReset: PrivateKernelResetCircuitPrivateInputs, + privateKernelInputsReset: PrivateKernelResetCircuitPrivateInputsVariants, ): Promise>; /** diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index 750735d8cef..09843ab2b03 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -56,7 +56,10 @@ export type CircuitName = | 'root-rollup' | 'private-kernel-init' | 'private-kernel-inner' - | 'private-kernel-reset' + | 'private-kernel-reset-full' + | 'private-kernel-reset-big' + | 'private-kernel-reset-medium' + | 'private-kernel-reset-small' | 'private-kernel-tail' | 'private-kernel-tail-to-public' | 'app-circuit' diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index 92b5928fc87..84f9e873016 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -30,7 +30,8 @@ }, "scripts": { "build": "yarn clean && yarn generate && tsc -b", - "generate": "./scripts/copy-contracts.sh", + "generate": "./scripts/copy-contracts.sh && yarn generate:reset-variants", + "generate:reset-variants": "node --no-warnings --loader ts-node/esm src/scripts/generate_reset_variants.ts && prettier -w src/structs/kernel/private_kernel_reset_circuit_private_inputs_variants.ts", "build:dev": "tsc -b --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint ./src", diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts index 831c6d70a82..d56371e9f13 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts @@ -30,7 +30,10 @@ describe('buildNoteHashReadRequestHints', () => { let noteHashReadRequests: Tuple; let noteHashes: Tuple; let noteHashLeafIndexMap: Map = new Map(); - let expectedHints: NoteHashReadRequestHints; + let expectedHints: NoteHashReadRequestHints< + typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX + >; let numReadRequests = 0; let numPendingReads = 0; let numSettledReads = 0; @@ -64,14 +67,26 @@ describe('buildNoteHashReadRequestHints', () => { numSettledReads++; }; - const buildHints = () => - buildNoteHashReadRequestHints(oracle, noteHashReadRequests, noteHashes, noteHashLeafIndexMap); + const buildHints = async () => + ( + await buildNoteHashReadRequestHints( + oracle, + noteHashReadRequests, + noteHashes, + noteHashLeafIndexMap, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + ) + ).hints; beforeEach(() => { noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => makeNoteHash(innerNoteHash(i))); noteHashLeafIndexMap = new Map(); - expectedHints = NoteHashReadRequestHintsBuilder.empty(); + expectedHints = NoteHashReadRequestHintsBuilder.empty( + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + ); numReadRequests = 0; numPendingReads = 0; numSettledReads = 0; diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts index 7fdfda24591..0c09f523b4c 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts @@ -22,15 +22,17 @@ function isValidNoteHashReadRequest(readRequest: ScopedReadRequest, noteHash: Sc ); } -export async function buildNoteHashReadRequestHints( +export async function buildNoteHashReadRequestHints( oracle: { getNoteHashMembershipWitness(leafIndex: bigint): Promise>; }, noteHashReadRequests: Tuple, noteHashes: Tuple, noteHashLeafIndexMap: Map, + sizePending: PENDING, + sizeSettled: SETTLED, ) { - const builder = new NoteHashReadRequestHintsBuilder(); + const builder = new NoteHashReadRequestHintsBuilder(sizePending, sizeSettled); const numReadRequests = countAccumulatedItems(noteHashReadRequests); diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts index bec3d9d5a8b..776f2324455 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts @@ -26,7 +26,10 @@ describe('buildNullifierReadRequestHints', () => { }; let nullifierReadRequests: Tuple; let nullifiers: Tuple; - let expectedHints: NullifierReadRequestHints; + let expectedHints: NullifierReadRequestHints< + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX + >; let numReadRequests = 0; let numPendingReads = 0; let numSettledReads = 0; @@ -69,12 +72,24 @@ describe('buildNullifierReadRequestHints', () => { numSettledReads++; }; - const buildHints = () => buildNullifierReadRequestHints(oracle, nullifierReadRequests, nullifiers); + const buildHints = async () => + ( + await buildNullifierReadRequestHints( + oracle, + nullifierReadRequests, + nullifiers, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + ) + ).hints; beforeEach(() => { nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); - expectedHints = NullifierReadRequestHintsBuilder.empty(); + expectedHints = NullifierReadRequestHintsBuilder.empty( + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + ); numReadRequests = 0; numPendingReads = 0; numSettledReads = 0; diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts index 9a1cbb38ae8..a10401c80ef 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts @@ -25,15 +25,17 @@ interface NullifierMembershipWitnessWithPreimage { leafPreimage: IndexedTreeLeafPreimage; } -export async function buildNullifierReadRequestHints( +export async function buildNullifierReadRequestHints( oracle: { getNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierReadRequests: Tuple, nullifiers: Tuple, + sizePending: PENDING, + sizeSettled: SETTLED, siloed = false, ) { - const builder = new NullifierReadRequestHintsBuilder(); + const builder = new NullifierReadRequestHintsBuilder(sizePending, sizeSettled); const numReadRequests = countAccumulatedItems(nullifierReadRequests); @@ -69,12 +71,14 @@ export async function buildNullifierReadRequestHints( return builder.toHints(); } -export function buildSiloedNullifierReadRequestHints( +export function buildSiloedNullifierReadRequestHints( oracle: { getNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierReadRequests: Tuple, nullifiers: Tuple, + sizePending: PENDING, + sizeSettled: SETTLED, ) { // Nullifiers outputted from public kernels are already siloed while read requests are not. // Siloing the read request values and set the contract addresses to zero to find the matching nullifier contexts. @@ -90,5 +94,5 @@ export function buildSiloedNullifierReadRequestHints( new Nullifier(n.value, n.counter, n.noteHash).scope(AztecAddress.ZERO), ) as Tuple; - return buildNullifierReadRequestHints(oracle, siloedReadRequests, scopedNullifiers, true); + return buildNullifierReadRequestHints(oracle, siloedReadRequests, scopedNullifiers, sizePending, sizeSettled, true); } diff --git a/yarn-project/circuits.js/src/scripts/generate_reset_variants.ts b/yarn-project/circuits.js/src/scripts/generate_reset_variants.ts new file mode 100644 index 00000000000..90380d66b08 --- /dev/null +++ b/yarn-project/circuits.js/src/scripts/generate_reset_variants.ts @@ -0,0 +1,125 @@ +import fs from 'fs'; +import path from 'path'; + +import { + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, +} from '../constants.gen.js'; + +interface ResetVariant { + tag: string; + priority: number; + replacements: { + NOTE_HASH_PENDING_AMOUNT: number; + NOTE_HASH_SETTLED_AMOUNT: number; + NULLIFIER_PENDING_AMOUNT: number; + NULLIFIER_SETTLED_AMOUNT: number; + NULLIFIER_KEYS: number; + }; +} + +const prelude = ` +// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +import { + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, +} from '../../constants.gen.js'; +import type { PrivateKernelResetCircuitPrivateInputs } from './private_kernel_reset_circuit_private_inputs.js'; +`; + +function buildPrivateResetVariantsObject(variants: ResetVariant[]): string { + let output = 'export const PRIVATE_RESET_VARIANTS = {'; + + for (const variant of variants) { + output += ` + ${variant.tag}: { + NOTE_HASH_PENDING_AMOUNT: ${variant.replacements.NOTE_HASH_PENDING_AMOUNT}, + NOTE_HASH_SETTLED_AMOUNT: ${variant.replacements.NOTE_HASH_SETTLED_AMOUNT}, + NULLIFIER_PENDING_AMOUNT: ${variant.replacements.NULLIFIER_PENDING_AMOUNT}, + NULLIFIER_SETTLED_AMOUNT: ${variant.replacements.NULLIFIER_SETTLED_AMOUNT}, + NULLIFIER_KEYS: ${variant.replacements.NULLIFIER_KEYS}, + },`; + } + + output += ` + full: { + NOTE_HASH_PENDING_AMOUNT: MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + NOTE_HASH_SETTLED_AMOUNT: MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + NULLIFIER_PENDING_AMOUNT: MAX_NULLIFIER_READ_REQUESTS_PER_TX, + NULLIFIER_SETTLED_AMOUNT: MAX_NULLIFIER_READ_REQUESTS_PER_TX, + NULLIFIER_KEYS: MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + }, + } as const;\n`; + return output; +} + +function buildPrivateResetVariantsType(variants: ResetVariant[]): string { + let output = 'export type PrivateKernelResetCircuitPrivateInputsVariants =\n'; + + for (const variant of variants) { + output += ` + | PrivateKernelResetCircuitPrivateInputs< + ${variant.replacements.NOTE_HASH_PENDING_AMOUNT}, + ${variant.replacements.NOTE_HASH_SETTLED_AMOUNT}, + ${variant.replacements.NULLIFIER_PENDING_AMOUNT}, + ${variant.replacements.NULLIFIER_SETTLED_AMOUNT}, + ${variant.replacements.NULLIFIER_KEYS}, + '${variant.tag}' + > + `; + } + + output += ` + | PrivateKernelResetCircuitPrivateInputs< + typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, + typeof MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + 'full' + >;`; + return output; +} + +function validateVariants(variants: ResetVariant[]) { + for (const variant of variants) { + if (variant.replacements.NOTE_HASH_PENDING_AMOUNT > MAX_NOTE_HASH_READ_REQUESTS_PER_TX) { + throw new Error(`NOTE_HASH_PENDING_AMOUNT must be less than ${MAX_NOTE_HASH_READ_REQUESTS_PER_TX}`); + } + if (variant.replacements.NOTE_HASH_SETTLED_AMOUNT > MAX_NOTE_HASH_READ_REQUESTS_PER_TX) { + throw new Error(`NOTE_HASH_SETTLED_AMOUNT must be less than ${MAX_NOTE_HASH_READ_REQUESTS_PER_TX}`); + } + if (variant.replacements.NULLIFIER_PENDING_AMOUNT > MAX_NULLIFIER_READ_REQUESTS_PER_TX) { + throw new Error(`NULLIFIER_PENDING_AMOUNT must be less than ${MAX_NULLIFIER_READ_REQUESTS_PER_TX}`); + } + if (variant.replacements.NULLIFIER_SETTLED_AMOUNT > MAX_NULLIFIER_READ_REQUESTS_PER_TX) { + throw new Error(`NULLIFIER_SETTLED_AMOUNT must be less than ${MAX_NULLIFIER_READ_REQUESTS_PER_TX}`); + } + if (variant.replacements.NULLIFIER_KEYS > MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) { + throw new Error(`NULLIFIER_KEYS must be less than ${MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX}`); + } + } +} + +const resetVariants: ResetVariant[] = JSON.parse( + fs.readFileSync(path.resolve('../../noir-projects/noir-protocol-circuits/reset_variants.json'), 'utf8'), +); + +// Sort them by decreasing priority so that the bigger circuits are tried later +resetVariants.sort((a, b) => b.priority - a.priority); + +validateVariants(resetVariants); + +fs.writeFileSync( + path.resolve('./src/structs/kernel/private_kernel_reset_circuit_private_inputs_variants.ts'), + ` +${prelude} + +${buildPrivateResetVariantsObject(resetVariants)} + +export type PrivateKernelResetTags = keyof typeof PRIVATE_RESET_VARIANTS; + +${buildPrivateResetVariantsType(resetVariants)}`, +); diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index e4e2b2b4194..9d763fe68ff 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -25,6 +25,7 @@ export * from './kernel/private_kernel_circuit_public_inputs.js'; export * from './kernel/private_kernel_data.js'; export * from './kernel/private_kernel_inner_circuit_private_inputs.js'; export * from './kernel/private_kernel_reset_circuit_private_inputs.js'; +export * from './kernel/private_kernel_reset_circuit_private_inputs_variants.js'; export * from './kernel/private_kernel_tail_circuit_private_inputs.js'; export * from './kernel/private_kernel_tail_circuit_public_inputs.js'; export * from './kernel/public_call_data.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts index 980af10d329..4c15cca12fa 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts @@ -1,19 +1,17 @@ -import { GrumpkinScalar } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, } from '../../constants.gen.js'; -import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; import { NoteLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; import { type NoteHashReadRequestHints, + NullifierKeyHint, type NullifierReadRequestHints, noteHashReadRequestHintsFromBuffer, nullifierReadRequestHintsFromBuffer, @@ -41,7 +39,13 @@ export class PrivateKernelResetOutputs { } } -export class PrivateKernelResetHints { +export class PrivateKernelResetHints< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, +> { constructor( /** * Contains hints for the transient note hashes to locate corresponding nullifiers. @@ -58,16 +62,16 @@ export class PrivateKernelResetHints { /** * Contains hints for the transient read requests to localize corresponding commitments. */ - public noteHashReadRequestHints: NoteHashReadRequestHints, + public noteHashReadRequestHints: NoteHashReadRequestHints, /** * Contains hints for the nullifier read requests to locate corresponding pending or settled nullifiers. */ - public nullifierReadRequestHints: NullifierReadRequestHints, + public nullifierReadRequestHints: NullifierReadRequestHints, /** * The master nullifier secret keys for the nullifier key validation requests. */ - public masterNullifierSecretKeys: Tuple, + public masterNullifierSecretKeys: Tuple, ) {} toBuffer() { @@ -81,20 +85,67 @@ export class PrivateKernelResetHints { ); } + trimToSizes< + NEW_NH_RR_PENDING extends number, + NEW_NH_RR_SETTLED extends number, + NEW_NLL_RR_PENDING extends number, + NEW_NLL_RR_SETTLED extends number, + NEW_NLL_KEYS extends number, + >( + numNoteHashReadRequestPending: NEW_NH_RR_PENDING, + numNoteHashReadRequestSettled: NEW_NH_RR_SETTLED, + numNullifierReadRequestPending: NEW_NLL_RR_PENDING, + numNullifierReadRequestSettled: NEW_NLL_RR_SETTLED, + numNullifierKeys: NEW_NLL_KEYS, + ): PrivateKernelResetHints< + NEW_NH_RR_PENDING, + NEW_NH_RR_SETTLED, + NEW_NLL_RR_PENDING, + NEW_NLL_RR_SETTLED, + NEW_NLL_KEYS + > { + return new PrivateKernelResetHints( + this.transientNullifierIndexesForNoteHashes, + this.transientNoteHashIndexesForNullifiers, + this.transientNoteHashIndexesForLogs, + this.noteHashReadRequestHints.trimToSizes(numNoteHashReadRequestPending, numNoteHashReadRequestSettled), + this.nullifierReadRequestHints.trimToSizes(numNullifierReadRequestPending, numNullifierReadRequestSettled), + this.masterNullifierSecretKeys.slice(0, numNullifierKeys) as Tuple, + ); + } /** * Deserializes from a buffer or reader. * @param buffer - Buffer or reader to read from. * @returns The deserialized instance. */ - static fromBuffer(buffer: Buffer | BufferReader) { + static fromBuffer< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, + >( + buffer: Buffer | BufferReader, + numNoteHashReadRequestPending: NH_RR_PENDING, + numNoteHashReadRequestSettled: NH_RR_SETTLED, + numNullifierReadRequestPending: NLL_RR_PENDING, + numNullifierReadRequestSettled: NLL_RR_SETTLED, + numNullifierKeys: NLL_KEYS, + ): PrivateKernelResetHints { const reader = BufferReader.asReader(buffer); return new PrivateKernelResetHints( reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), reader.readNumbers(MAX_NOTE_ENCRYPTED_LOGS_PER_TX), - reader.readObject({ fromBuffer: noteHashReadRequestHintsFromBuffer }), - reader.readObject({ fromBuffer: nullifierReadRequestHintsFromBuffer }), - reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), + reader.readObject({ + fromBuffer: buf => + noteHashReadRequestHintsFromBuffer(buf, numNoteHashReadRequestPending, numNoteHashReadRequestSettled), + }), + reader.readObject({ + fromBuffer: buf => + nullifierReadRequestHintsFromBuffer(buf, numNullifierReadRequestPending, numNullifierReadRequestSettled), + }), + reader.readArray(numNullifierKeys, NullifierKeyHint), ); } } @@ -102,14 +153,22 @@ export class PrivateKernelResetHints { /** * Input to the private kernel circuit - reset call. */ -export class PrivateKernelResetCircuitPrivateInputs { +export class PrivateKernelResetCircuitPrivateInputs< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, + TAG extends string, +> { constructor( /** * The previous kernel data */ public previousKernel: PrivateKernelData, public outputs: PrivateKernelResetOutputs, - public hints: PrivateKernelResetHints, + public hints: PrivateKernelResetHints, + public sizeTag: TAG, ) {} isForPublic() { @@ -129,12 +188,45 @@ export class PrivateKernelResetCircuitPrivateInputs { * @param buffer - Buffer or reader to read from. * @returns The deserialized instance. */ - static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelResetCircuitPrivateInputs { + static fromBuffer< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, + TAG extends string, + >( + buffer: Buffer | BufferReader, + numNoteHashReadRequestPending: NH_RR_PENDING, + numNoteHashReadRequestSettled: NH_RR_SETTLED, + numNullifierReadRequestPending: NLL_RR_PENDING, + numNullifierReadRequestSettled: NLL_RR_SETTLED, + numNullifierKeys: NLL_KEYS, + sizeTag: TAG, + ): PrivateKernelResetCircuitPrivateInputs< + NH_RR_PENDING, + NH_RR_SETTLED, + NLL_RR_PENDING, + NLL_RR_SETTLED, + NLL_KEYS, + TAG + > { const reader = BufferReader.asReader(buffer); return new PrivateKernelResetCircuitPrivateInputs( reader.readObject(PrivateKernelData), reader.readObject(PrivateKernelResetOutputs), - reader.readObject(PrivateKernelResetHints), + reader.readObject({ + fromBuffer: buf => + PrivateKernelResetHints.fromBuffer( + buf, + numNoteHashReadRequestPending, + numNoteHashReadRequestSettled, + numNullifierReadRequestPending, + numNullifierReadRequestSettled, + numNullifierKeys, + ), + }), + sizeTag, ); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index 14943e0e59b..c6f22d4b536 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,6 +1,6 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_PUBLIC_DATA_HINTS } from '../../constants.gen.js'; +import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS } from '../../constants.gen.js'; import { type NullifierNonExistentReadRequestHints, nullifierNonExistentReadRequestHintsFromBuffer, @@ -20,7 +20,10 @@ export class PublicKernelTailCircuitPrivateInputs { /** * Contains hints for the nullifier read requests to locate corresponding pending or settled nullifiers. */ - public readonly nullifierReadRequestHints: NullifierReadRequestHints, + public readonly nullifierReadRequestHints: NullifierReadRequestHints< + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, + typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX + >, /** * Contains hints for the nullifier non existent read requests. */ @@ -53,7 +56,11 @@ export class PublicKernelTailCircuitPrivateInputs { const reader = BufferReader.asReader(buffer); return new PublicKernelTailCircuitPrivateInputs( reader.readObject(PublicKernelData), - nullifierReadRequestHintsFromBuffer(reader), + nullifierReadRequestHintsFromBuffer( + reader, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + ), nullifierNonExistentReadRequestHintsFromBuffer(reader), reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), reader.readObject(PublicDataReadRequestHints), diff --git a/yarn-project/circuits.js/src/structs/read_request_hints/index.ts b/yarn-project/circuits.js/src/structs/read_request_hints/index.ts index b0b5692505e..c140118984c 100644 --- a/yarn-project/circuits.js/src/structs/read_request_hints/index.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints/index.ts @@ -1,3 +1,4 @@ export * from './note_hash_read_request_hints.js'; export * from './nullifier_read_request_hints.js'; export * from './read_request_hints.js'; +export * from './nullifier_key_hint.js'; diff --git a/yarn-project/circuits.js/src/structs/read_request_hints/note_hash_read_request_hints.ts b/yarn-project/circuits.js/src/structs/read_request_hints/note_hash_read_request_hints.ts index edc7f672219..55ae64a2ae2 100644 --- a/yarn-project/circuits.js/src/structs/read_request_hints/note_hash_read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints/note_hash_read_request_hints.ts @@ -14,42 +14,46 @@ import { type NoteHashLeafValue = Fr; -export type NoteHashReadRequestHints = ReadRequestResetHints< - typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, +export type NoteHashReadRequestHints = ReadRequestResetHints< typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + PENDING, + SETTLED, typeof NOTE_HASH_TREE_HEIGHT, NoteHashLeafValue >; -export function noteHashReadRequestHintsFromBuffer(buffer: Buffer | BufferReader): NoteHashReadRequestHints { +export function noteHashReadRequestHintsFromBuffer( + buffer: Buffer | BufferReader, + numPending: PENDING, + numSettled: SETTLED, +): NoteHashReadRequestHints { return ReadRequestResetHints.fromBuffer( buffer, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + numPending, + numSettled, NOTE_HASH_TREE_HEIGHT, Fr, ); } -export class NoteHashReadRequestHintsBuilder { - private hints: NoteHashReadRequestHints; - private numPendingReadHints = 0; - private numSettledReadHints = 0; +export class NoteHashReadRequestHintsBuilder { + private hints: NoteHashReadRequestHints; + public numPendingReadHints = 0; + public numSettledReadHints = 0; - constructor() { + constructor(numPending: PENDING, numSettled: SETTLED) { this.hints = new ReadRequestResetHints( makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ReadRequestStatus.nada), - makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, () => PendingReadHint.nada(MAX_NOTE_HASH_READ_REQUESTS_PER_TX)), - makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, () => + makeTuple(numPending, () => PendingReadHint.nada(MAX_NOTE_HASH_READ_REQUESTS_PER_TX)), + makeTuple(numSettled, () => SettledReadHint.nada(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, Fr.zero), ), ); } - static empty() { - return new NoteHashReadRequestHintsBuilder().toHints(); + static empty(numPending: PENDING, numSettled: SETTLED) { + return new NoteHashReadRequestHintsBuilder(numPending, numSettled).toHints().hints; } addPendingReadRequest(readRequestIndex: number, noteHashIndex: number) { @@ -79,6 +83,10 @@ export class NoteHashReadRequestHintsBuilder { } toHints() { - return this.hints; + return { + numPendingReadHints: this.numPendingReadHints, + numSettledReadHints: this.numSettledReadHints, + hints: this.hints, + }; } } diff --git a/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_key_hint.ts b/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_key_hint.ts new file mode 100644 index 00000000000..cb9d55f81e4 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_key_hint.ts @@ -0,0 +1,20 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; + +export class NullifierKeyHint { + constructor(public privateKey: GrumpkinPrivateKey, public requestIndex: number) {} + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new NullifierKeyHint(reader.readObject(GrumpkinPrivateKey), reader.readNumber()); + } + + toBuffer() { + return serializeToBuffer(this.privateKey, this.requestIndex); + } + + static empty() { + return new NullifierKeyHint(GrumpkinPrivateKey.zero(), 0); + } +} diff --git a/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_read_request_hints.ts b/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_read_request_hints.ts index abccc72c816..0f78e722470 100644 --- a/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints/nullifier_read_request_hints.ts @@ -13,42 +13,46 @@ import { SettledReadHint, } from './read_request_hints.js'; -export type NullifierReadRequestHints = ReadRequestResetHints< - typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, - typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, +export type NullifierReadRequestHints = ReadRequestResetHints< typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, + PENDING, + SETTLED, typeof NULLIFIER_TREE_HEIGHT, TreeLeafPreimage >; -export function nullifierReadRequestHintsFromBuffer(buffer: Buffer | BufferReader): NullifierReadRequestHints { +export function nullifierReadRequestHintsFromBuffer( + buffer: Buffer | BufferReader, + numPendingReads: PENDING, + numSettledReads: SETTLED, +): NullifierReadRequestHints { return ReadRequestResetHints.fromBuffer( buffer, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, + numPendingReads, + numSettledReads, NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage, ); } -export class NullifierReadRequestHintsBuilder { - private hints: NullifierReadRequestHints; +export class NullifierReadRequestHintsBuilder { + private hints: NullifierReadRequestHints; private numPendingReadHints = 0; private numSettledReadHints = 0; - constructor() { + constructor(numPending: PENDING, numSettled: SETTLED) { this.hints = new ReadRequestResetHints( makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestStatus.nada), - makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, () => PendingReadHint.nada(MAX_NULLIFIER_READ_REQUESTS_PER_TX)), - makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, () => + makeTuple(numPending, () => PendingReadHint.nada(MAX_NULLIFIER_READ_REQUESTS_PER_TX)), + makeTuple(numSettled, () => SettledReadHint.nada(MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage.empty), ), ); } - static empty() { - return new NullifierReadRequestHintsBuilder().toHints(); + static empty(numPending: PENDING, numSettled: SETTLED) { + return new NullifierReadRequestHintsBuilder(numPending, numSettled).toHints().hints; } addPendingReadRequest(readRequestIndex: number, nullifierIndex: number) { @@ -78,6 +82,10 @@ export class NullifierReadRequestHintsBuilder { } toHints() { - return this.hints; + return { + numPendingReadHints: this.numPendingReadHints, + numSettledReadHints: this.numSettledReadHints, + hints: this.hints, + }; } } diff --git a/yarn-project/circuits.js/src/structs/read_request_hints/read_request_hints.ts b/yarn-project/circuits.js/src/structs/read_request_hints/read_request_hints.ts index ba3d0b02d94..8c2b81c6165 100644 --- a/yarn-project/circuits.js/src/structs/read_request_hints/read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints/read_request_hints.ts @@ -105,6 +105,20 @@ export class ReadRequestResetHints< public settledReadHints: Tuple, NUM_SETTLED_READS>, ) {} + trimToSizes( + numPendingReads: NEW_NUM_PENDING_READS, + numSettledReads: NEW_NUM_SETTLED_READS, + ): ReadRequestResetHints { + return new ReadRequestResetHints( + this.readRequestStatuses, + this.pendingReadHints.slice(0, numPendingReads) as Tuple, + this.settledReadHints.slice(0, numSettledReads) as Tuple< + SettledReadHint, + NEW_NUM_SETTLED_READS + >, + ); + } + /** * Deserializes from a buffer or reader. * @param buffer - Buffer or reader to read from. diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 47664f24fd3..eeba483929d 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -681,7 +681,7 @@ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCirc export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernelTailCircuitPrivateInputs { return new PublicKernelTailCircuitPrivateInputs( makePublicKernelData(seed), - NullifierReadRequestHintsBuilder.empty(), + NullifierReadRequestHintsBuilder.empty(MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX), NullifierNonExistentReadRequestHintsBuilder.empty(), makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), PublicDataReadRequestHintsBuilder.empty(), diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index 48be3f815e4..a9168a22063 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -9,7 +9,8 @@ import { type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, type PrivateKernelInnerCircuitPrivateInputs, - type PrivateKernelResetCircuitPrivateInputs, + type PrivateKernelResetCircuitPrivateInputsVariants, + type PrivateKernelResetTags, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, type PublicKernelCircuitPrivateInputs, @@ -23,7 +24,7 @@ import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log' import { type NoirCompiledCircuit } from '@aztec/types/noir'; import { type ForeignCallInput, type ForeignCallOutput } from '@noir-lang/acvm_js'; -import { type CompiledCircuit } from '@noir-lang/noir_js'; +import { type CompiledCircuit, type InputMap, Noir } from '@noir-lang/noir_js'; import { type Abi, abiDecode, abiEncode } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; import { strict as assert } from 'assert'; @@ -35,7 +36,13 @@ import PrivateKernelInitSimulatedJson from './target/private_kernel_init_simulat import PrivateKernelInnerJson from './target/private_kernel_inner.json' assert { type: 'json' }; import PrivateKernelInnerSimulatedJson from './target/private_kernel_inner_simulated.json' assert { type: 'json' }; import PrivateKernelResetJson from './target/private_kernel_reset.json' assert { type: 'json' }; +import PrivateKernelResetBigJson from './target/private_kernel_reset_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumJson from './target/private_kernel_reset_medium.json' assert { type: 'json' }; import PrivateKernelResetSimulatedJson from './target/private_kernel_reset_simulated.json' assert { type: 'json' }; +import PrivateKernelResetBigSimulatedJson from './target/private_kernel_reset_simulated_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumSimulatedJson from './target/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; +import PrivateKernelResetSmallSimulatedJson from './target/private_kernel_reset_simulated_small.json' assert { type: 'json' }; +import PrivateKernelResetSmallJson from './target/private_kernel_reset_small.json' assert { type: 'json' }; import PrivateKernelTailJson from './target/private_kernel_tail.json' assert { type: 'json' }; import PrivateKernelTailSimulatedJson from './target/private_kernel_tail_simulated.json' assert { type: 'json' }; import PrivateKernelTailToPublicJson from './target/private_kernel_tail_to_public.json' assert { type: 'json' }; @@ -84,7 +91,6 @@ import { type PrivateKernelTailReturnType as TailReturnType, PrivateKernelInit as executePrivateKernelInitWithACVM, PrivateKernelInner as executePrivateKernelInnerWithACVM, - PrivateKernelReset as executePrivateKernelResetWithACVM, PrivateKernelTailToPublic as executePrivateKernelTailToPublicWithACVM, PrivateKernelTail as executePrivateKernelTailWithACVM, } from './types/index.js'; @@ -142,6 +148,19 @@ export const MergeRollupArtifact = MergeRollupJson as NoirCompiledCircuit; export const RootRollupArtifact = RootRollupJson as NoirCompiledCircuit; +export type PrivateResetArtifacts = + | 'PrivateKernelResetFullArtifact' + | 'PrivateKernelResetBigArtifact' + | 'PrivateKernelResetMediumArtifact' + | 'PrivateKernelResetSmallArtifact'; + +export const PrivateResetTagToArtifactName: Record = { + full: 'PrivateKernelResetFullArtifact', + big: 'PrivateKernelResetBigArtifact', + medium: 'PrivateKernelResetMediumArtifact', + small: 'PrivateKernelResetSmallArtifact', +}; + export type ServerProtocolArtifact = | 'PublicKernelSetupArtifact' | 'PublicKernelAppLogicArtifact' @@ -156,9 +175,9 @@ export type ServerProtocolArtifact = export type ClientProtocolArtifact = | 'PrivateKernelInitArtifact' | 'PrivateKernelInnerArtifact' - | 'PrivateKernelResetArtifact' | 'PrivateKernelTailArtifact' - | 'PrivateKernelTailToPublicArtifact'; + | 'PrivateKernelTailToPublicArtifact' + | PrivateResetArtifacts; export type ProtocolArtifact = ServerProtocolArtifact | ClientProtocolArtifact; @@ -177,26 +196,17 @@ export const ServerCircuitArtifacts: Record = { PrivateKernelInitArtifact: PrivateKernelInitArtifact, PrivateKernelInnerArtifact: PrivateKernelInnerArtifact, - PrivateKernelResetArtifact: PrivateKernelResetArtifact, + PrivateKernelResetFullArtifact: PrivateKernelResetArtifact, + PrivateKernelResetBigArtifact: PrivateKernelResetBigJson as NoirCompiledCircuit, + PrivateKernelResetMediumArtifact: PrivateKernelResetMediumJson as NoirCompiledCircuit, + PrivateKernelResetSmallArtifact: PrivateKernelResetSmallJson as NoirCompiledCircuit, PrivateKernelTailArtifact: PrivateKernelTailArtifact, PrivateKernelTailToPublicArtifact: PrivateKernelTailToPublicArtifact, }; export const ProtocolCircuitArtifacts: Record = { - PrivateKernelInitArtifact: PrivateKernelInitArtifact, - PrivateKernelInnerArtifact: PrivateKernelInnerArtifact, - PrivateKernelResetArtifact: PrivateKernelResetArtifact, - PrivateKernelTailArtifact: PrivateKernelTailArtifact, - PrivateKernelTailToPublicArtifact: PrivateKernelTailToPublicArtifact, - PublicKernelSetupArtifact: PublicKernelSetupArtifact, - PublicKernelAppLogicArtifact: PublicKernelAppLogicArtifact, - PublicKernelTeardownArtifact: PublicKernelTeardownArtifact, - PublicKernelTailArtifact: PublicKernelTailArtifact, - BaseParityArtifact: BaseParityArtifact, - RootParityArtifact: RootParityArtifact, - BaseRollupArtifact: BaseRollupArtifact, - MergeRollupArtifact: MergeRollupArtifact, - RootRollupArtifact: RootRollupArtifact, + ...ClientCircuitArtifacts, + ...ServerCircuitArtifacts, }; /** @@ -233,21 +243,29 @@ export async function executeInner( return mapPrivateKernelCircuitPublicInputsFromNoir(returnType); } +const ResetSimulatedArtifacts: Record = { + PrivateKernelResetFullArtifact: PrivateKernelResetSimulatedJson as CompiledCircuit, + PrivateKernelResetBigArtifact: PrivateKernelResetBigSimulatedJson as CompiledCircuit, + PrivateKernelResetMediumArtifact: PrivateKernelResetMediumSimulatedJson as CompiledCircuit, + PrivateKernelResetSmallArtifact: PrivateKernelResetSmallSimulatedJson as CompiledCircuit, +}; + /** * Executes the inner private kernel. * @param privateKernelResetCircuitPrivateInputs - The private inputs to the reset private kernel. * @returns The public inputs. */ export async function executeReset( - privateKernelResetCircuitPrivateInputs: PrivateKernelResetCircuitPrivateInputs, + privateKernelResetCircuitPrivateInputs: PrivateKernelResetCircuitPrivateInputsVariants, ): Promise { - const returnType = await executePrivateKernelResetWithACVM( - mapPrivateKernelResetCircuitPrivateInputsToNoir(privateKernelResetCircuitPrivateInputs), - PrivateKernelResetSimulatedJson as CompiledCircuit, - foreignCallHandler, - ); - - return mapPrivateKernelCircuitPublicInputsFromNoir(returnType); + const artifact = + ResetSimulatedArtifacts[PrivateResetTagToArtifactName[privateKernelResetCircuitPrivateInputs.sizeTag]]; + const program = new Noir(artifact); + const args: InputMap = { + input: mapPrivateKernelResetCircuitPrivateInputsToNoir(privateKernelResetCircuitPrivateInputs as any), + }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return mapPrivateKernelCircuitPublicInputsFromNoir(returnValue as any); } /** @@ -316,10 +334,12 @@ export function convertPrivateKernelInnerInputsToWitnessMap( * @returns The witness map */ export function convertPrivateKernelResetInputsToWitnessMap( - privateKernelResetCircuitPrivateInputs: PrivateKernelResetCircuitPrivateInputs, + privateKernelResetCircuitPrivateInputs: PrivateKernelResetCircuitPrivateInputsVariants, ): WitnessMap { - const mapped = mapPrivateKernelResetCircuitPrivateInputsToNoir(privateKernelResetCircuitPrivateInputs); - const initialWitnessMap = abiEncode(PrivateKernelResetArtifact.abi as Abi, { input: mapped as any }); + const mapped = mapPrivateKernelResetCircuitPrivateInputsToNoir(privateKernelResetCircuitPrivateInputs as any); + const artifact = + ClientCircuitArtifacts[PrivateResetTagToArtifactName[privateKernelResetCircuitPrivateInputs.sizeTag]]; + const initialWitnessMap = abiEncode(artifact.abi as Abi, { input: mapped as any }); return initialWitnessMap; } @@ -384,9 +404,13 @@ export function convertPrivateKernelInnerOutputsFromWitnessMap(outputs: WitnessM * @param outputs - The private kernel outputs as a witness map. * @returns The public inputs. */ -export function convertPrivateKernelResetOutputsFromWitnessMap(outputs: WitnessMap): PrivateKernelCircuitPublicInputs { +export function convertPrivateKernelResetOutputsFromWitnessMap( + outputs: WitnessMap, + sizeTag: PrivateKernelResetTags, +): PrivateKernelCircuitPublicInputs { // Decode the witness map into two fields, the return values and the inputs - const decodedInputs: DecodedInputs = abiDecode(PrivateKernelResetArtifact.abi as Abi, outputs); + const artifact = ClientCircuitArtifacts[PrivateResetTagToArtifactName[sizeTag]]; + const decodedInputs: DecodedInputs = abiDecode(artifact.abi as Abi, outputs); // Cast the inputs as the return type const returnType = decodedInputs.return_value as ResetReturnType; 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 51581bd197d..e759fb55253 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 @@ -7,12 +7,14 @@ import fs from 'fs/promises'; const log = createConsoleLogger('aztec:noir-contracts'); +const resetCircuit = 'private_kernel_reset'; + const circuits = [ 'parity_base', 'parity_root', 'private_kernel_init', 'private_kernel_inner', - 'private_kernel_reset', + resetCircuit, 'private_kernel_tail', 'private_kernel_tail_to_public', 'public_kernel_setup', @@ -25,6 +27,14 @@ const circuits = [ ]; const main = async () => { + const resetVariants = JSON.parse( + await fs.readFile('../../noir-projects/noir-protocol-circuits/reset_variants.json', 'utf8'), + ); + + for (const variant of resetVariants) { + circuits.push(`${resetCircuit}_${variant.tag}`); + } + try { await fs.access('./src/types/'); } catch (error) { 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 2f6ef2aa908..1d5fa16fe4c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -165,6 +165,7 @@ import type { NoteHashReadRequestHints as NoteHashReadRequestHintsNoir, NoteHashSettledReadHint as NoteHashSettledReadHintNoir, NoteLogHash as NoteLogHashNoir, + NullifierKeyHint as NullifierKeyHintNoir, NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, NullifierLeafPreimage as NullifierLeafPreimageNoir, Nullifier as NullifierNoir, @@ -306,6 +307,21 @@ export function mapGrumpkinPrivateKeyToNoir(privateKey: GrumpkinPrivateKey): Gru }; } +/** + * Maps a NullifierKeyHint to noir. + * @param hint - The nullifier key hint. + * @returns The nullifier key hint mapped to noir types. + */ +export function mapNullifierKeyHintToNoir(hint: { + privateKey: GrumpkinPrivateKey; + requestIndex: number; +}): NullifierKeyHintNoir { + return { + private_key: mapGrumpkinPrivateKeyToNoir(hint.privateKey), + request_index: mapNumberToNoir(hint.requestIndex), + }; +} + /** * Maps a noir GrumpkinPrivateKey to a GrumpkinPrivateKey. * @param privateKey - The noir GrumpkinPrivateKey. @@ -1016,19 +1032,36 @@ function mapNullifierSettledReadHintToNoir( }; } -function mapNoteHashReadRequestHintsToNoir(hints: NoteHashReadRequestHints): NoteHashReadRequestHintsNoir { +function mapNoteHashReadRequestHintsToNoir( + hints: NoteHashReadRequestHints, +): NoteHashReadRequestHintsNoir { return { read_request_statuses: mapTuple(hints.readRequestStatuses, mapReadRequestStatusToNoir), - pending_read_hints: mapTuple(hints.pendingReadHints, mapPendingReadHintToNoir), - settled_read_hints: mapTuple(hints.settledReadHints, mapNoteHashSettledReadHintToNoir), + pending_read_hints: hints.pendingReadHints.map(mapPendingReadHintToNoir) as FixedLengthArray< + PendingReadHintNoir, + PENDING + >, + settled_read_hints: hints.settledReadHints.map(mapNoteHashSettledReadHintToNoir) as FixedLengthArray< + NoteHashSettledReadHintNoir, + SETTLED + >, }; } -function mapNullifierReadRequestHintsToNoir(hints: NullifierReadRequestHints): NullifierReadRequestHintsNoir { +function mapNullifierReadRequestHintsToNoir( + hints: NullifierReadRequestHints, +): NullifierReadRequestHintsNoir { return { read_request_statuses: mapTuple(hints.readRequestStatuses, mapReadRequestStatusToNoir), - pending_read_hints: mapTuple(hints.pendingReadHints, mapPendingReadHintToNoir), - settled_read_hints: mapTuple(hints.settledReadHints, mapNullifierSettledReadHintToNoir), + pending_read_hints: hints.pendingReadHints.map(mapPendingReadHintToNoir) as FixedLengthArray< + PendingReadHintNoir, + PENDING + >, + settled_read_hints: hints.settledReadHints.map(settledHint => + mapNullifierSettledReadHintToNoir( + settledHint as SettledReadHint, + ), + ) as FixedLengthArray, }; } @@ -1520,7 +1553,15 @@ function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): Privat }; } -function mapPrivateKernelResetHintsToNoir(inputs: PrivateKernelResetHints): PrivateKernelResetHintsNoir { +function mapPrivateKernelResetHintsToNoir< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, +>( + inputs: PrivateKernelResetHints, +): PrivateKernelResetHintsNoir { return { transient_nullifier_indexes_for_note_hashes: mapTuple( inputs.transientNullifierIndexesForNoteHashes, @@ -1530,13 +1571,30 @@ function mapPrivateKernelResetHintsToNoir(inputs: PrivateKernelResetHints): Priv transient_note_hash_indexes_for_logs: mapTuple(inputs.transientNoteHashIndexesForLogs, mapNumberToNoir), note_hash_read_request_hints: mapNoteHashReadRequestHintsToNoir(inputs.noteHashReadRequestHints), nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), - master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), - }; -} - -export function mapPrivateKernelResetCircuitPrivateInputsToNoir( - inputs: PrivateKernelResetCircuitPrivateInputs, -): PrivateKernelResetCircuitPrivateInputsNoir { + master_nullifier_secret_keys: inputs.masterNullifierSecretKeys.map(mapNullifierKeyHintToNoir) as FixedLengthArray< + NullifierKeyHintNoir, + NLL_KEYS + >, + }; +} + +export function mapPrivateKernelResetCircuitPrivateInputsToNoir< + NH_RR_PENDING extends number, + NH_RR_SETTLED extends number, + NLL_RR_PENDING extends number, + NLL_RR_SETTLED extends number, + NLL_KEYS extends number, + TAG extends string, +>( + inputs: PrivateKernelResetCircuitPrivateInputs< + NH_RR_PENDING, + NH_RR_SETTLED, + NLL_RR_PENDING, + NLL_RR_SETTLED, + NLL_KEYS, + TAG + >, +): PrivateKernelResetCircuitPrivateInputsNoir { return { previous_kernel: mapPrivateKernelDataToNoir(inputs.previousKernel), outputs: mapPrivateKernelResetOutputsToNoir(inputs.outputs), diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 6a88d0a2791..88431b4c145 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -9,7 +9,6 @@ import { PrivateKernelData, PrivateKernelInitCircuitPrivateInputs, PrivateKernelInnerCircuitPrivateInputs, - PrivateKernelResetCircuitPrivateInputs, PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, type RECURSIVE_PROOF_LENGTH, @@ -28,8 +27,7 @@ import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNote import { buildPrivateKernelInitHints, buildPrivateKernelInnerHints, - buildPrivateKernelResetHints, - buildPrivateKernelResetOutputs, + buildPrivateKernelResetInputs, buildPrivateKernelTailHints, } from './private_inputs_builders/index.js'; import { type ProvingDataOracle } from './proving_data_oracle.js'; @@ -137,18 +135,8 @@ export class KernelProver { assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), ); - const expectedOutputs = buildPrivateKernelResetOutputs( - output.publicInputs.end.newNoteHashes, - output.publicInputs.end.newNullifiers, - output.publicInputs.end.noteEncryptedLogsHashes, - ); - output = await this.proofCreator.createProofReset( - new PrivateKernelResetCircuitPrivateInputs( - previousKernelData, - expectedOutputs, - await buildPrivateKernelResetHints(output.publicInputs, noteHashLeafIndexMap, this.oracle), - ), + await buildPrivateKernelResetInputs(previousKernelData, noteHashLeafIndexMap, this.oracle), ); previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts index 1449ceec2ac..6eef626d510 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts @@ -1,14 +1,18 @@ import { type Fr, - GrumpkinScalar, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - type MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, - type PrivateKernelCircuitPublicInputs, + NullifierKeyHint, + PRIVATE_RESET_VARIANTS, + type PrivateKernelData, + PrivateKernelResetCircuitPrivateInputs, + type PrivateKernelResetCircuitPrivateInputsVariants, PrivateKernelResetHints, type ScopedNullifier, type ScopedNullifierKeyValidationRequest, @@ -21,11 +25,14 @@ import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; import { type ProvingDataOracle } from '../proving_data_oracle.js'; +import { buildPrivateKernelResetOutputs } from './build_private_kernel_reset_outputs.js'; -function getNullifierReadRequestHints( +function getNullifierReadRequestHints( nullifierReadRequests: Tuple, nullifiers: Tuple, oracle: ProvingDataOracle, + sizePending: PENDING, + sizeSettled: SETTLED, ) { const getNullifierMembershipWitness = async (nullifier: Fr) => { const res = await oracle.getNullifierMembershipWitness(nullifier); @@ -44,7 +51,13 @@ function getNullifierReadRequestHints( }; }; - return buildNullifierReadRequestHints({ getNullifierMembershipWitness }, nullifierReadRequests, nullifiers); + return buildNullifierReadRequestHints( + { getNullifierMembershipWitness }, + nullifierReadRequests, + nullifiers, + sizePending, + sizeSettled, + ); } async function getMasterNullifierSecretKeys( @@ -54,36 +67,59 @@ async function getMasterNullifierSecretKeys( >, oracle: ProvingDataOracle, ) { - const keys = makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar.zero); + const keys = makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, NullifierKeyHint.empty); + + let keyIndex = 0; for (let i = 0; i < nullifierKeyValidationRequests.length; ++i) { const request = nullifierKeyValidationRequests[i].request; if (request.isEmpty()) { break; } - keys[i] = await oracle.getMasterNullifierSecretKey(request.masterNullifierPublicKey); + keys[keyIndex] = new NullifierKeyHint( + await oracle.getMasterNullifierSecretKey(request.masterNullifierPublicKey), + i, + ); + keyIndex++; } - return keys; + return { + keysCount: keyIndex, + keys, + }; } -export async function buildPrivateKernelResetHints( - publicInputs: PrivateKernelCircuitPublicInputs, +export async function buildPrivateKernelResetInputs( + previousKernelData: PrivateKernelData, noteHashLeafIndexMap: Map, oracle: ProvingDataOracle, ) { - const noteHashReadRequestHints = await buildNoteHashReadRequestHints( + const publicInputs = previousKernelData.publicInputs; + // Use max sizes, they will be trimmed down later. + const { + numPendingReadHints: noteHashPendingReadHints, + numSettledReadHints: noteHashSettledReadHints, + hints: noteHashReadRequestHints, + } = await buildNoteHashReadRequestHints( oracle, publicInputs.validationRequests.noteHashReadRequests, publicInputs.end.newNoteHashes, noteHashLeafIndexMap, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ); - const nullifierReadRequestHints = await getNullifierReadRequestHints( + const { + numPendingReadHints: nullifierPendingReadHints, + numSettledReadHints: nullifierSettledReadHints, + hints: nullifierReadRequestHints, + } = await getNullifierReadRequestHints( publicInputs.validationRequests.nullifierReadRequests, publicInputs.end.newNullifiers, oracle, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, ); - const masterNullifierSecretKeys = await getMasterNullifierSecretKeys( + const { keysCount: nullifierKeysCount, keys: masterNullifierSecretKeys } = await getMasterNullifierSecretKeys( publicInputs.validationRequests.nullifierKeyValidationRequests, oracle, ); @@ -101,12 +137,48 @@ export async function buildPrivateKernelResetHints( MAX_NOTE_ENCRYPTED_LOGS_PER_TX, ); - return new PrivateKernelResetHints( - transientNullifierIndexesForNoteHashes, - transientNoteHashIndexesForNullifiers, - transientNoteHashIndexesForLogs, - noteHashReadRequestHints, - nullifierReadRequestHints, - masterNullifierSecretKeys, + const expectedOutputs = buildPrivateKernelResetOutputs( + previousKernelData.publicInputs.end.newNoteHashes, + previousKernelData.publicInputs.end.newNullifiers, + previousKernelData.publicInputs.end.noteEncryptedLogsHashes, ); + + let privateInputs; + + for (const [sizeTag, hintSizes] of Object.entries(PRIVATE_RESET_VARIANTS)) { + if ( + hintSizes.NOTE_HASH_PENDING_AMOUNT >= noteHashPendingReadHints && + hintSizes.NOTE_HASH_SETTLED_AMOUNT >= noteHashSettledReadHints && + hintSizes.NULLIFIER_PENDING_AMOUNT >= nullifierPendingReadHints && + hintSizes.NULLIFIER_SETTLED_AMOUNT >= nullifierSettledReadHints && + hintSizes.NULLIFIER_KEYS >= nullifierKeysCount + ) { + privateInputs = new PrivateKernelResetCircuitPrivateInputs( + previousKernelData, + expectedOutputs, + new PrivateKernelResetHints( + transientNullifierIndexesForNoteHashes, + transientNoteHashIndexesForNullifiers, + transientNoteHashIndexesForLogs, + noteHashReadRequestHints, + nullifierReadRequestHints, + masterNullifierSecretKeys, + ).trimToSizes( + hintSizes.NOTE_HASH_PENDING_AMOUNT, + hintSizes.NOTE_HASH_SETTLED_AMOUNT, + hintSizes.NULLIFIER_PENDING_AMOUNT, + hintSizes.NULLIFIER_SETTLED_AMOUNT, + hintSizes.NULLIFIER_KEYS, + ), + sizeTag, + ); + break; + } + } + + if (!privateInputs) { + throw new Error('No private inputs found for the given hint sizes.'); + } + + return privateInputs as PrivateKernelResetCircuitPrivateInputsVariants; } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts index de292d85327..07dee2ce561 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts @@ -1,5 +1,5 @@ export { buildPrivateKernelInitHints } from './build_private_kernel_init_hints.js'; export { buildPrivateKernelInnerHints } from './build_private_kernel_inner_hints.js'; export { buildPrivateKernelTailHints } from './build_private_kernel_tail_hints.js'; -export { buildPrivateKernelResetHints } from './build_private_kernel_reset_hints.js'; +export { buildPrivateKernelResetInputs } from './build_private_kernel_reset_hints.js'; export { buildPrivateKernelResetOutputs } from './build_private_kernel_reset_outputs.js'; diff --git a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts index ff919257d4b..97ca1c230fc 100644 --- a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts @@ -1,12 +1,12 @@ import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; -import { type CircuitSimulationStats } from '@aztec/circuit-types/stats'; +import type { CircuitName, CircuitSimulationStats } from '@aztec/circuit-types/stats'; import { NESTED_RECURSIVE_PROOF_LENGTH, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, type PrivateKernelInnerCircuitPrivateInputs, - type PrivateKernelResetCircuitPrivateInputs, + type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, @@ -67,12 +67,12 @@ export class TestProofCreator implements ProofCreator { } public async createProofReset( - privateInputs: PrivateKernelResetCircuitPrivateInputs, + privateInputs: PrivateKernelResetCircuitPrivateInputsVariants, ): Promise> { const [duration, result] = await elapsed(() => executeReset(privateInputs)); this.log.debug(`Simulated private kernel reset`, { eventName: 'circuit-simulation', - circuitName: 'private-kernel-reset', + circuitName: ('private-kernel-reset-' + privateInputs.sizeTag) as CircuitName, duration, inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index 0d83cd44db4..a7cf24f1726 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -3,7 +3,7 @@ import { type Fr, type MAX_NEW_NULLIFIERS_PER_TX, type MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - type MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, type MAX_PUBLIC_DATA_HINTS, type MAX_PUBLIC_DATA_READS_PER_TX, type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -27,11 +27,19 @@ import { type IndexedTreeId, type MerkleTreeOperations } from '@aztec/world-stat export class HintsBuilder { constructor(private db: MerkleTreeOperations) {} - getNullifierReadRequestHints( + async getNullifierReadRequestHints( nullifierReadRequests: Tuple, pendingNullifiers: Tuple, ) { - return buildSiloedNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers); + return ( + await buildSiloedNullifierReadRequestHints( + this, + nullifierReadRequests, + pendingNullifiers, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + ) + ).hints; } getNullifierNonExistentReadRequestHints(