From 2acc8429bf6c48f5741a5193db4f71c1d3776cff Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Thu, 2 May 2024 14:31:29 +0000 Subject: [PATCH 01/13] Silo note hashes and nullifiers in private tail. --- .../kernel_circuit_public_inputs_composer.nr | 28 ++++-- ...e_kernel_circuit_public_inputs_composer.nr | 30 ++---- .../src/private_kernel_inner.nr | 2 +- .../src/private_kernel_tail.nr | 91 ++++++++--------- .../src/private_kernel_tail_to_public.nr | 97 ++++++++++--------- .../src/public_kernel_app_logic.nr | 13 ++- .../src/public_kernel_tail.nr | 5 +- .../src/note_hash_read_request_reset.nr | 6 +- .../src/nullifier_read_request_reset.nr | 5 +- .../private_validation_request_processor.nr | 4 +- .../src/reset/transient_data.nr | 44 +++++---- .../src/tests/squash_transient_data.nr | 6 +- .../private_accumulated_data.nr | 4 +- .../private_accumulated_data_builder.nr | 53 ++++++---- .../crates/types/src/abis/note_hash.nr | 46 ++------- .../crates/types/src/abis/nullifier.nr | 97 +++++++++++++++++-- .../crates/types/src/constants.nr | 3 +- .../crates/types/src/tests/fixture_builder.nr | 53 +++++----- 18 files changed, 340 insertions(+), 247 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index fee2d1293ac..db62d9084fd 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -3,13 +3,14 @@ use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, PublicKernelCircuitPublicInputs}, - note_hash::NoteHashContext, nullifier::Nullifier, side_effect::{SideEffect, Ordered}, gas::Gas + note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::{SideEffect, Ordered}, + gas::Gas }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash}, + hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, silo_note_hash, silo_nullifier}, utils::arrays::{array_length, array_to_bounded_vec, assert_sorted_array} }; @@ -25,13 +26,13 @@ struct KernelCircuitPublicInputsComposer { previous_kernel: PrivateKernelData, // Final data note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], // Hints 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], sorted_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -43,12 +44,12 @@ impl KernelCircuitPublicInputsComposer { pub fn new( previous_kernel: PrivateKernelData, note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], 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], sorted_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -122,6 +123,7 @@ impl KernelCircuitPublicInputsComposer { fn silo_values(&mut self) { self.silo_note_hashes(); + self.silo_nullifiers(); // TODO: Move siloing from init/inner circuits to here. } @@ -133,13 +135,25 @@ impl KernelCircuitPublicInputsComposer { for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { let note_hash = note_hashes[i]; if note_hash.value != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); let nonce = compute_note_hash_nonce(first_nullifier.value, i); - let unique_note_hash = compute_unique_siloed_note_hash(nonce, note_hash.value); + let unique_note_hash = compute_unique_siloed_note_hash(nonce, siloed); self.public_inputs.end.new_note_hashes.storage[i].value = unique_note_hash; } } } + fn silo_nullifiers(&mut self) { + let nullifiers = self.public_inputs.end.new_nullifiers.storage; + for i in 1..MAX_NEW_NOTE_HASHES_PER_TX { // i starts from 1 to skip the first nullifier. + let nullifier = nullifiers[i]; + if nullifier.value != 0 { + let siloed = silo_nullifier(nullifier.contract_address, nullifier.value); + self.public_inputs.end.new_nullifiers.storage[i].value = siloed; + } + } + } + fn propagate_rollup_validation_requests(&mut self) { self.public_inputs.validation_requests.max_block_number = self.previous_kernel.public_inputs.validation_requests.for_rollup.max_block_number; } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index f50048579aa..c474d2ce756 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -2,7 +2,7 @@ use dep::types::{ abis::{ call_request::CallRequest, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder}, - max_block_number::MaxBlockNumber, nullifier::Nullifier, + max_block_number::MaxBlockNumber, nullifier::NullifierContext, private_circuit_public_inputs::PrivateCircuitPublicInputs }, address::AztecAddress, @@ -10,8 +10,8 @@ use dep::types::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL }, - hash::{compute_l2_to_l1_hash, silo_note_hash, silo_nullifier}, traits::is_empty, - transaction::tx_request::TxRequest, utils::arrays::array_to_bounded_vec + hash::compute_l2_to_l1_hash, traits::is_empty, transaction::tx_request::TxRequest, + utils::arrays::array_to_bounded_vec }; struct DataSource { @@ -38,7 +38,9 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.min_revertible_side_effect_counter = private_call_public_inputs.min_revertible_side_effect_counter; // Since it's the first iteration, we need to push the the tx hash nullifier into the `new_nullifiers` array - public_inputs.end.new_nullifiers.push(Nullifier { value: tx_request.hash(), note_hash: 0, counter: 0 }); + public_inputs.end.new_nullifiers.push( + NullifierContext { value: tx_request.hash(), note_hash: 0, counter: 0, contract_address: AztecAddress::zero() } + ); // Note that we do not need to nullify the transaction request nonce anymore. // Should an account want to additionally use nonces for replay protection or handling cancellations, // they will be able to do so in the account contract logic: @@ -150,12 +152,9 @@ impl PrivateKernelCircuitPublicInputsComposer { if note_hash.value != 0 { let nullifier_counter = source.note_hash_nullifier_counters[i]; assert( - (nullifier_counter == 0) | (nullifier_counter > note_hash.counter), "invalid nullifier counter" + (nullifier_counter == 0) | (nullifier_counter > note_hash.counter), "Invalid nullifier counter" ); - - // TODO: Silo values in the tail circuit. - note_hash.value = silo_note_hash(source.storage_contract_address, note_hash.value); - self.public_inputs.end.new_note_hashes.push(note_hash.to_context(nullifier_counter)); + self.public_inputs.end.new_note_hashes.push(note_hash.to_context(nullifier_counter, source.storage_contract_address)); } } } @@ -165,18 +164,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..nullifiers.len() { let nullifier = nullifiers[i]; if nullifier.value != 0 { - let siloed_note_hash = if nullifier.note_hash == 0 { - 0 - } else { - silo_note_hash(source.storage_contract_address, nullifier.note_hash) - }; - self.public_inputs.end.new_nullifiers.push( - Nullifier { - value: silo_nullifier(source.storage_contract_address, nullifier.value), - counter: nullifier.counter, - note_hash: siloed_note_hash - } - ); + self.public_inputs.end.new_nullifiers.push(nullifier.to_context(source.storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index e7671e53d0b..911a5c63c0c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -504,7 +504,7 @@ mod tests { assert_eq(public_inputs.end.new_note_hashes[2].nullifier_counter, 20); } - #[test(should_fail_with="invalid nullifier counter")] + #[test(should_fail_with="Invalid nullifier counter")] fn propagate_note_hashes_with_incorrect_nullifier_counters_fails() { let mut builder = PrivateKernelInnerInputsBuilder::new(); builder.private_call.public_inputs.new_note_hashes.push(NoteHash { value: 12, counter: 3 }); 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 f38d494395b..8b3e53f9f10 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - note_hash::NoteHashContext, nullifier::Nullifier, side_effect::SideEffect + note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -15,7 +15,7 @@ use dep::types::{ // Can just be KernelCircuitPublicInputs. struct PrivateKernelTailOutputs { note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], } struct PrivateKernelTailHints { @@ -26,7 +26,7 @@ struct PrivateKernelTailHints { master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], sorted_new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -49,7 +49,7 @@ impl PrivateKernelTailCircuitPrivateInputs { let note_hash_tree_root = previous_public_inputs.constants.historical_header.state.partial.note_hash_tree.root; let nullifier_tree_root = previous_public_inputs.constants.historical_header.state.partial.nullifier_tree.root; - let request_processor = PrivateValidationRequestProcessor { + PrivateValidationRequestProcessor { validation_requests: previous_public_inputs.validation_requests, note_hash_read_request_hints: self.hints.note_hash_read_request_hints, pending_note_hashes: previous_public_inputs.end.new_note_hashes, @@ -58,10 +58,9 @@ impl PrivateKernelTailCircuitPrivateInputs { pending_nullifiers: previous_public_inputs.end.new_nullifiers, nullifier_tree_root, master_nullifier_secret_keys: self.hints.master_nullifier_secret_keys - }; - request_processor.validate(); + }.validate(); - let mut composer = KernelCircuitPublicInputsComposer::new( + KernelCircuitPublicInputsComposer::new( self.previous_kernel, self.outputs.note_hashes, self.outputs.nullifiers, @@ -75,8 +74,7 @@ impl PrivateKernelTailCircuitPrivateInputs { self.hints.sorted_encrypted_log_hashes_indexes, self.hints.sorted_unencrypted_log_hashes, self.hints.sorted_unencrypted_log_hashes_indexes - ); - composer.compose().finish() + ).compose().finish() } } @@ -99,10 +97,10 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::NoteHashContext, nullifier::Nullifier, side_effect::{SideEffect, Ordered}, gas::Gas + note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, side_effect::SideEffect, gas::Gas }, grumpkin_private_key::GrumpkinPrivateKey, - hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, sha256_to_field}, + hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, sha256_to_field, silo_note_hash, silo_nullifier}, tests::{fixture_builder::FixtureBuilder, sort::sort_get_sorted_hints}, utils::{arrays::{array_eq, array_length}}, traits::{Empty, is_empty, is_empty_array} }; @@ -134,21 +132,32 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. - pub fn compute_unique_siloed_note_hashes( + pub fn compute_output_note_hashes( self, note_hashes: [NoteHashContext; N] ) -> [Field; N] { let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0); let mut unique_siloed_note_hashes = [0; N]; for i in 0..N { - if note_hashes[i].value != 0 { + let note_hash = note_hashes[i]; + if note_hash.value != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); let nonce = compute_note_hash_nonce(first_nullifier.value, i); - unique_siloed_note_hashes[i] = compute_unique_siloed_note_hash(nonce, note_hashes[i].value); + unique_siloed_note_hashes[i] = compute_unique_siloed_note_hash(nonce, siloed); } } unique_siloed_note_hashes } + pub fn compute_output_nullifiers(_self: Self, nullifiers: [NullifierContext; N]) -> [Field; N] { + let mut output = [0; N]; + output[0] = nullifiers[0].value; + for i in 1..N { + output[i] = silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value); + } + output + } + pub fn add_pending_note_hash_read_request(&mut self, note_hash_index: u64) { let read_request_index = self.previous_kernel.add_read_request_for_pending_note_hash(note_hash_index); let hint_index = self.note_hash_read_request_hints_builder.pending_read_hints.len(); @@ -183,7 +192,7 @@ mod tests { let sorted = sort_get_sorted_hints( self.previous_kernel.new_nullifiers.storage, - |a: Nullifier, b: Nullifier| a.counter < b.counter + |a: NullifierContext, b: NullifierContext| a.counter < b.counter ); let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; @@ -394,15 +403,12 @@ mod tests { builder.nullify_pending_note_hash(1, 0); let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); + assert(is_empty_array(public_inputs.end.new_note_hashes)); // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0].value, new_nullifiers[2].value] - ) - ); + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0], new_nullifiers[2]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -413,23 +419,16 @@ mod tests { // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; - // The 0th hash will be chopped. - let unique_siloed_note_hashes = builder.compute_unique_siloed_note_hashes([new_note_hashes[1]]); let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); - assert( - array_eq( - public_inputs.end.new_note_hashes, - [unique_siloed_note_hashes[0]] - ) - ); + + // The 0th hash is chopped. + let expected_note_hashes = builder.compute_output_note_hashes([new_note_hashes[1]]); + assert(array_eq(public_inputs.end.new_note_hashes, expected_note_hashes)); + // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0].value, new_nullifiers[2].value] - ) - ); + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0], new_nullifiers[2]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -444,9 +443,11 @@ mod tests { let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); - // Only the first nullifier is left after squashing. assert(is_empty_array(public_inputs.end.new_note_hashes)); - assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0].value])); + + // Only the first nullifier is left after squashing. + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -477,9 +478,11 @@ mod tests { let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); - // Only the first nullifier is left after squashing. assert(is_empty_array(public_inputs.end.new_note_hashes)); - assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0].value])); + + // Only the first nullifier is left after squashing. + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -493,7 +496,7 @@ mod tests { let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; let mut reversed_note_hashes = [NoteHashContext::empty(); 10]; - let mut reversed_nullifiers = [Nullifier::empty(); 10]; + let mut reversed_nullifiers = [NullifierContext::empty(); 10]; for i in 0..10 { reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); @@ -503,13 +506,13 @@ mod tests { builder.previous_kernel.new_note_hashes.extend_from_array(reversed_note_hashes); builder.previous_kernel.new_nullifiers.extend_from_array(reversed_nullifiers); - let sorted_unique_note_hashes = builder.compute_unique_siloed_note_hashes(sorted_note_hashes); - let public_inputs = builder.execute(); + let expected_note_hashes = builder.compute_output_note_hashes(sorted_note_hashes); + let expected_nullifiers = builder.compute_output_nullifiers(sorted_nullifiers); for i in 0..10 { - assert(public_inputs.end.new_note_hashes[i].eq(sorted_unique_note_hashes[i])); - assert(public_inputs.end.new_nullifiers[i].eq(sorted_nullifiers[i].value)); + assert(public_inputs.end.new_note_hashes[i].eq(expected_note_hashes[i])); + assert(public_inputs.end.new_nullifiers[i].eq(expected_nullifiers[i])); } } 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 aa1726db148..3806250a683 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::NoteHashContext, nullifier::Nullifier, side_effect::SideEffect + note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -15,7 +15,7 @@ use dep::types::{ // Can just be PublicKernelCircuitPublicInputs. struct PrivateKernelTailToPublicOutputs { note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], } struct PrivateKernelTailToPublicHints { @@ -26,7 +26,7 @@ struct PrivateKernelTailToPublicHints { master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], sorted_new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -49,7 +49,7 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { let note_hash_tree_root = previous_public_inputs.constants.historical_header.state.partial.note_hash_tree.root; let nullifier_tree_root = previous_public_inputs.constants.historical_header.state.partial.nullifier_tree.root; - let request_processor = PrivateValidationRequestProcessor { + PrivateValidationRequestProcessor { validation_requests: previous_public_inputs.validation_requests, note_hash_read_request_hints: self.hints.note_hash_read_request_hints, pending_note_hashes: previous_public_inputs.end.new_note_hashes, @@ -58,10 +58,9 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { pending_nullifiers: previous_public_inputs.end.new_nullifiers, nullifier_tree_root, master_nullifier_secret_keys: self.hints.master_nullifier_secret_keys - }; - request_processor.validate(); + }.validate(); - let mut composer = KernelCircuitPublicInputsComposer::new( + KernelCircuitPublicInputsComposer::new( self.previous_kernel, self.outputs.note_hashes, self.outputs.nullifiers, @@ -75,8 +74,7 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { self.hints.sorted_encrypted_log_hashes_indexes, self.hints.sorted_unencrypted_log_hashes, self.hints.sorted_unencrypted_log_hashes_indexes - ); - composer.compose_public().finish_to_public() + ).compose_public().finish_to_public() } } @@ -101,10 +99,11 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, - note_hash::{NoteHash, NoteHashContext}, nullifier::Nullifier, side_effect::{SideEffect, Ordered} + note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, + side_effect::SideEffect }, grumpkin_private_key::GrumpkinPrivateKey, - hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash}, + hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, silo_note_hash, silo_nullifier}, tests::{fixture_builder::FixtureBuilder, sort::sort_get_sorted_hints}, utils::{arrays::{array_eq, array_length}}, traits::is_empty_array }; @@ -136,17 +135,16 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. - pub fn compute_unique_siloed_note_hashes( - self, - note_hashes: [NoteHashContext; N] - ) -> [NoteHash; N] { + pub fn compute_output_note_hashes(self, note_hashes: [NoteHashContext; N]) -> [NoteHash; N] { let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0); let mut unique_siloed_note_hashes = [NoteHash::empty(); N]; for i in 0..N { - if note_hashes[i].value != 0 { + let note_hash = note_hashes[i]; + if note_hash.value != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); let nonce = compute_note_hash_nonce(first_nullifier.value, i); unique_siloed_note_hashes[i] = NoteHash { - value: compute_unique_siloed_note_hash(nonce, note_hashes[i].value), + value: compute_unique_siloed_note_hash(nonce, siloed), counter: 0, // Counter is cleared so it's not exposed to the public. }; } @@ -154,6 +152,18 @@ mod tests { unique_siloed_note_hashes } + pub fn compute_output_nullifiers( + _self: Self, + nullifiers: [NullifierContext; N] + ) -> [Nullifier; N] { + let mut output = [Nullifier::empty(); N]; + output[0].value = nullifiers[0].value; + for i in 1..N { + output[i] = Nullifier { value: silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value), counter: 0, note_hash: 0 }; + } + output + } + pub fn add_pending_note_hash_read_request(&mut self, note_hash_index: u64) { let read_request_index = self.previous_kernel.add_read_request_for_pending_note_hash(note_hash_index); let hint_index = self.note_hash_read_request_hints_builder.pending_read_hints.len(); @@ -188,7 +198,7 @@ mod tests { let sorted = sort_get_sorted_hints( self.previous_kernel.new_nullifiers.storage, - |a: Nullifier, b: Nullifier| a.counter < b.counter + |a: NullifierContext, b: NullifierContext| a.counter < b.counter ); let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; @@ -341,15 +351,12 @@ mod tests { builder.nullify_pending_note_hash(1, 0); let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); + assert(is_empty_array(public_inputs.end.new_note_hashes)); // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0], new_nullifiers[2]] - ) - ); + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0], new_nullifiers[2]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -360,23 +367,16 @@ mod tests { // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; - // The 0th hash will be chopped. - let unique_siloed_note_hashes = builder.compute_unique_siloed_note_hashes([new_note_hashes[1]]); let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); - assert( - array_eq( - public_inputs.end.new_note_hashes, - [unique_siloed_note_hashes[0]] - ) - ); + + // The 0th hash will be chopped. + let expected_note_hashes = builder.compute_output_note_hashes([new_note_hashes[1]]); + assert(array_eq(public_inputs.end.new_note_hashes, expected_note_hashes)); + // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0], new_nullifiers[2]] - ) - ); + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0], new_nullifiers[2]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -393,7 +393,8 @@ mod tests { // Only the first nullifier is left after squashing. assert(is_empty_array(public_inputs.end.new_note_hashes)); - assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0]])); + let expected_nullifiers = builder.compute_output_nullifiers([new_nullifiers[0]]); + assert(array_eq(public_inputs.end.new_nullifiers, expected_nullifiers)); } #[test] @@ -407,7 +408,7 @@ mod tests { let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; let mut reversed_note_hashes = [NoteHashContext::empty(); 10]; - let mut reversed_nullifiers = [Nullifier::empty(); 10]; + let mut reversed_nullifiers = [NullifierContext::empty(); 10]; for i in 0..10 { reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); @@ -417,13 +418,13 @@ mod tests { builder.previous_kernel.new_note_hashes.extend_from_array(reversed_note_hashes); builder.previous_kernel.new_nullifiers.extend_from_array(reversed_nullifiers); - let sorted_unique_note_hashes = builder.compute_unique_siloed_note_hashes(sorted_note_hashes); - let public_inputs = builder.execute(); + let output_note_hashes = builder.compute_output_note_hashes(sorted_note_hashes); + let output_nullifiers = builder.compute_output_nullifiers(sorted_nullifiers); for i in 0..10 { - assert(public_inputs.end.new_note_hashes[i].eq(sorted_unique_note_hashes[i])); - assert(public_inputs.end.new_nullifiers[i].eq(sorted_nullifiers[i])); + assert(public_inputs.end.new_note_hashes[i].eq(output_note_hashes[i])); + assert(public_inputs.end.new_nullifiers[i].eq(output_nullifiers[i])); } } @@ -487,17 +488,19 @@ mod tests { let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; let public_inputs = builder.execute(); + let output_nullifiers = builder.compute_output_nullifiers(new_nullifiers); + assert( array_eq( public_inputs.end_non_revertible.new_nullifiers, - [new_nullifiers[0], new_nullifiers[1], new_nullifiers[2]] + [output_nullifiers[0], output_nullifiers[1], output_nullifiers[2]] ) ); assert( array_eq( public_inputs.end.new_nullifiers, - [new_nullifiers[3], new_nullifiers[4]] + [output_nullifiers[3], output_nullifiers[4]] ) ); @@ -521,7 +524,7 @@ mod tests { let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; let public_inputs = builder.execute(); - let siloed_note_hashes = builder.compute_unique_siloed_note_hashes(new_note_hashes); + let siloed_note_hashes = builder.compute_output_note_hashes(new_note_hashes); assert( array_eq( diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index d6123c39ac6..f51fcc03f35 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -78,8 +78,9 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::{NoteHash, NoteHashContext}, nullifier::Nullifier, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest + note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + read_request::ReadRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, hash::{compute_l2_to_l1_hash, silo_note_hash, silo_nullifier}, @@ -186,7 +187,7 @@ mod tests { let contract_address = builder.public_call.contract_address; // Setup 2 new note hashes on the previous kernel. builder.previous_kernel.append_new_note_hashes(2); - let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: NoteHashContext| n.to_note_hash()); + let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: NoteHashContext| NoteHash { value: n.value, counter: n.counter }); // Setup 2 new note hashes on the current public inputs. let current = [ NoteHash { value: previous[1].value + 1, counter: 3 }, @@ -247,19 +248,21 @@ mod tests { // Setup 2 new nullifiers on the previous kernel. builder.previous_kernel.append_new_nullifiers(2); - let previous = builder.previous_kernel.new_nullifiers.storage; + let previous = builder.previous_kernel.new_nullifiers.storage.map( + |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } + ); // Setup 2 new note hashes on the current public inputs. let current = [ Nullifier { value: previous[1].value + 1, note_hash: 0, counter: 4 }, Nullifier { value: previous[1].value + 2, note_hash: 0, counter: 5 } ]; + builder.public_call.public_inputs.new_nullifiers.extend_from_array(current); let siloed = current.map( |current: Nullifier| Nullifier { value: silo_nullifier(contract_address, current.value), note_hash: current.note_hash, counter: current.counter } ); - builder.public_call.public_inputs.new_nullifiers.extend_from_array(current); // There are 2 revertible nullifiers in the previous kernel. // The tx nullifier is part of the non-revertible nullifiers. let new_nullifiers = [previous[0], previous[1], siloed[0], siloed[1]]; 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 ffe93c8dfd0..67b65e16fbc 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 @@ -115,7 +115,8 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, kernel_data::PublicKernelData, - nullifier_leaf_preimage::NullifierLeafPreimage, membership_witness::PublicDataMembershipWitness + nullifier::{Nullifier, NullifierContext}, nullifier_leaf_preimage::NullifierLeafPreimage, + membership_witness::PublicDataMembershipWitness }, constants::{ MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, @@ -229,6 +230,8 @@ mod tests { let nullifiers = array_merge( self.previous_kernel.new_nullifiers.storage, self.previous_revertible.new_nullifiers.storage + ).map( + |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } ); self.nullifier_non_existent_read_request_hints_builder.set_nullifiers(nullifiers); } 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 8c40d7c2cf3..310a455da19 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 @@ -71,8 +71,10 @@ mod tests { ReadRequestContext { value: inner_note_hashes[3], counter: 78, contract_address }, // pending ]; - // TODO(#6122): Pending values shouldn't have been siloed at this point. - global pending_values = [NoteHashContext { value: note_hashes[2], counter: 2, nullifier_counter: 0 }, NoteHashContext { value: note_hashes[3], counter: 8, nullifier_counter: 0 }]; + global pending_values = [ + NoteHashContext { value: inner_note_hashes[2], counter: 2, nullifier_counter: 0, contract_address }, + NoteHashContext { value: inner_note_hashes[3], counter: 8, nullifier_counter: 0, contract_address }, + ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, PendingReadHint { read_request_index: 2, pending_value_index: 0 }, 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 ba2c15edc39..47c26125c34 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 @@ -67,7 +67,10 @@ mod tests { ReadRequestContext { value: inner_nullifiers[3], counter: 78, contract_address }, // pending ]; - global pending_values = [Nullifier { value: nullifiers[2], counter: 2, note_hash: 0 }, Nullifier { value: nullifiers[3], counter: 8, note_hash: 0 }]; + global pending_values = [ + Nullifier { value: inner_nullifiers[2], counter: 2, note_hash: 0 }, + Nullifier { value: inner_nullifiers[3], counter: 8, note_hash: 0 }, + ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, PendingReadHint { read_request_index: 2, pending_value_index: 0 }, 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 2d5adcd31cd..199f5655db9 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 @@ -3,7 +3,7 @@ use crate::{ nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests }; use dep::types::{ - abis::{note_hash::NoteHashContext, nullifier::Nullifier, validation_requests::ValidationRequests}, + abis::{note_hash::NoteHashContext, nullifier::NullifierContext, validation_requests::ValidationRequests}, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M @@ -17,7 +17,7 @@ struct PrivateValidationRequestProcessor { pending_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, nullifier_read_request_hints: NullifierReadRequestHints, - pending_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + pending_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], nullifier_tree_root: Field, master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index 56ef524f2dd..a403f23332a 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -1,10 +1,10 @@ -use dep::types::{abis::{note_hash::NoteHashContext, nullifier::Nullifier}, traits::is_empty}; +use dep::types::{abis::{note_hash::NoteHashContext, nullifier::NullifierContext}, traits::is_empty}; pub fn verify_squashed_transient_note_hashes_and_nullifiers( note_hashes: [NoteHashContext; NUM_NOTE_HASHES], - nullifiers: [Nullifier; NUM_NULLIFIERS], + nullifiers: [NullifierContext; NUM_NULLIFIERS], expected_note_hashes: [NoteHashContext; NUM_NOTE_HASHES], - expected_nullifiers: [Nullifier; NUM_NULLIFIERS], + expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS] ) { @@ -62,35 +62,37 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers { num_note_hashes: u64, num_nullifiers: u64, note_hashes: [NoteHashContext; NUM_NOTE_HASHES], - nullifiers: [Nullifier; NUM_NULLIFIERS], + nullifiers: [NullifierContext; NUM_NULLIFIERS], expected_note_hashes: [NoteHashContext; NUM_NOTE_HASHES], - expected_nullifiers: [Nullifier; NUM_NULLIFIERS], + expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS], } impl TestDataBuilder { pub fn default() -> TestDataBuilder<3, 3> { + let contract_address = AztecAddress::from_field(987654); + let note_hashes = [ - NoteHashContext { value: 11, counter: 100, nullifier_counter: 500 }, - NoteHashContext { value: 22, counter: 200, nullifier_counter: 0 }, - NoteHashContext { value: 33, counter: 300, nullifier_counter: 400 } + NoteHashContext { value: 11, counter: 100, nullifier_counter: 500, contract_address }, + NoteHashContext { value: 22, counter: 200, nullifier_counter: 0, contract_address }, + NoteHashContext { value: 33, counter: 300, nullifier_counter: 400, contract_address } ]; let nullifiers = [ - Nullifier { value: 44, counter: 400, note_hash: 33 }, - Nullifier { value: 55, counter: 500, note_hash: 11 }, - Nullifier { value: 66, counter: 600, note_hash: 0 } + NullifierContext { value: 44, counter: 400, note_hash: 33, contract_address }, + NullifierContext { value: 55, counter: 500, note_hash: 11, contract_address }, + NullifierContext { value: 66, counter: 600, note_hash: 0, contract_address } ]; let expected_note_hashes = [note_hashes[1], NoteHashContext::empty(), NoteHashContext::empty()]; - let expected_nullifiers = [nullifiers[2], Nullifier::empty(), Nullifier::empty()]; + let expected_nullifiers = [nullifiers[2], NullifierContext::empty(), NullifierContext::empty()]; let transient_nullifier_indexes_for_note_hashes = [1, 3, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 3]; @@ -108,20 +110,22 @@ mod tests { } pub fn default_all_clear() -> TestDataBuilder<3, 3> { + let contract_address = AztecAddress::from_field(987654); + let note_hashes = [ - NoteHashContext { value: 11, counter: 100, nullifier_counter: 500 }, - NoteHashContext { value: 22, counter: 200, nullifier_counter: 600 }, - NoteHashContext { value: 33, counter: 300, nullifier_counter: 400 } + NoteHashContext { value: 11, counter: 100, nullifier_counter: 500, contract_address }, + NoteHashContext { value: 22, counter: 200, nullifier_counter: 600, contract_address }, + NoteHashContext { value: 33, counter: 300, nullifier_counter: 400, contract_address } ]; let nullifiers = [ - Nullifier { value: 44, counter: 400, note_hash: 33 }, - Nullifier { value: 55, counter: 500, note_hash: 11 }, - Nullifier { value: 66, counter: 600, note_hash: 22 } + NullifierContext { value: 44, counter: 400, note_hash: 33, contract_address }, + NullifierContext { value: 55, counter: 500, note_hash: 11, contract_address }, + NullifierContext { value: 66, counter: 600, note_hash: 22, contract_address } ]; let expected_note_hashes = [NoteHashContext::empty(); 3]; - let expected_nullifiers = [Nullifier::empty(); 3]; + let expected_nullifiers = [NullifierContext::empty(); 3]; let transient_nullifier_indexes_for_note_hashes = [1, 2, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 1]; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr index 48446480718..409ed06d5b9 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr @@ -1,4 +1,4 @@ -use dep::types::abis::{note_hash::NoteHashContext, nullifier::Nullifier}; +use dep::types::abis::{note_hash::NoteHashContext, nullifier::NullifierContext}; pub fn squash_transient_note_hashes(note_hashes: [NoteHashContext; N]) -> [NoteHashContext; N] { let mut final_note_hashes = [NoteHashContext::empty(); N]; @@ -15,8 +15,8 @@ pub fn squash_transient_note_hashes(note_hashes: [NoteHashContext; N]) -> [No final_note_hashes } -pub fn squash_transient_nullifiers(nullifiers: [Nullifier; N]) -> [Nullifier; N] { - let mut final_nullifiers = [Nullifier::empty(); N]; +pub fn squash_transient_nullifiers(nullifiers: [NullifierContext; N]) -> [NullifierContext; N] { + let mut final_nullifiers = [NullifierContext::empty(); N]; let mut num_nullifiers = 0; for i in 0..N { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 31c73652ee0..31f9d29d9d0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - call_request::CallRequest, gas::Gas, note_hash::NoteHashContext, nullifier::Nullifier, + call_request::CallRequest, gas::Gas, note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect } }; @@ -12,7 +12,7 @@ use crate::constants::{ struct PrivateAccumulatedData { new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 984a1a292a1..d4e929809c7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -7,7 +7,7 @@ use crate::{ private_accumulated_data::PrivateAccumulatedData, public_accumulated_data::PublicAccumulatedData, public_accumulated_data_builder::PublicAccumulatedDataBuilder }, - call_request::CallRequest, note_hash::{NoteHash, NoteHashContext}, nullifier::Nullifier, + call_request::CallRequest, note_hash::{NoteHash, NoteHashContext}, nullifier::NullifierContext, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, constants::{ @@ -25,7 +25,7 @@ use crate::{ // .split_to_public: PublicKernelCircuitPublicInputs.(end,end_non_revertible) struct PrivateAccumulatedDataBuilder { new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, + new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -64,7 +64,7 @@ impl PrivateAccumulatedDataBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: Nullifier| n.value), + new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, encrypted_logs_hash, unencrypted_logs_hash, @@ -139,14 +139,15 @@ impl PrivateAccumulatedDataBuilder { for i in 0..MAX_NEW_NULLIFIERS_PER_TX { let nullifier = self.new_nullifiers.storage[i]; + let public_nullifier = nullifier.expose_to_public(); if nullifier.counter < min_revertible_side_effect_counter { - non_revertible_builder.new_nullifiers.push(nullifier); - if !is_empty(nullifier) { + non_revertible_builder.new_nullifiers.push(public_nullifier); + if !is_empty(public_nullifier) { non_revertible_da_gas_used += DA_GAS_PER_FIELD; } } else { - revertible_builder.new_nullifiers.push(nullifier); - if !is_empty(nullifier) { + revertible_builder.new_nullifiers.push(public_nullifier); + if !is_empty(public_nullifier) { revertible_da_gas_used += DA_GAS_PER_FIELD; } } @@ -198,7 +199,7 @@ mod tests { abis::{ accumulated_data::private_accumulated_data_builder::PrivateAccumulatedDataBuilder, gas::Gas, call_request::CallRequest, caller_context::CallerContext, - note_hash::{NoteHash, NoteHashContext}, nullifier::Nullifier, + note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, address::AztecAddress, utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} @@ -209,13 +210,13 @@ mod tests { let mut builder = PrivateAccumulatedDataBuilder::empty(); let non_revertible_note_hashes = [ - NoteHashContext { value: 1, counter: 1, nullifier_counter: 20 }, - NoteHashContext { value: 2, counter: 3, nullifier_counter: 5 } + NoteHashContext { value: 1, counter: 1, nullifier_counter: 20, contract_address: AztecAddress::from_field(7788) }, + NoteHashContext { value: 2, counter: 3, nullifier_counter: 5, contract_address: AztecAddress::from_field(5566) } ]; let non_revertible_nullifiers = [ - Nullifier { value: 10, note_hash: 1, counter: 2 }, - Nullifier { value: 20, note_hash: 2, counter: 4 } + NullifierContext { value: 10, note_hash: 1, counter: 2, contract_address: AztecAddress::from_field(9900) }, + NullifierContext { value: 20, note_hash: 2, counter: 4, contract_address: AztecAddress::from_field(7788) } ]; let non_revertible_public_stack = [ @@ -236,13 +237,13 @@ mod tests { ]; let revertible_note_hashes = [ - NoteHashContext { value: 3, counter: 7, nullifier_counter: 15 }, - NoteHashContext { value: 4, counter: 10, nullifier_counter: 0 } + NoteHashContext { value: 3, counter: 7, nullifier_counter: 15, contract_address: AztecAddress::from_field(9900) }, + NoteHashContext { value: 4, counter: 10, nullifier_counter: 0, contract_address: AztecAddress::from_field(7788) } ]; let revertible_nullifiers = [ - Nullifier { value: 30, note_hash: 3, counter: 8 }, - Nullifier { value: 40, note_hash: 4, counter: 11 } + NullifierContext { value: 30, note_hash: 3, counter: 8, contract_address: AztecAddress::from_field(9900) }, + NullifierContext { value: 40, note_hash: 4, counter: 11, contract_address: AztecAddress::from_field(5566) } ]; let revertible_public_call_stack = [ @@ -275,7 +276,15 @@ mod tests { ] ) ); - assert(array_eq(non_revertible.new_nullifiers, non_revertible_nullifiers)); + assert( + array_eq( + non_revertible.new_nullifiers, + [ + Nullifier { value: 10, note_hash: 0, counter: 0 }, + Nullifier { value: 20, note_hash: 0, counter: 0 } + ] + ) + ); assert(array_eq(non_revertible.public_call_stack, non_revertible_public_stack)); assert( @@ -287,7 +296,15 @@ mod tests { ] ) ); - assert(array_eq(revertible.new_nullifiers, revertible_nullifiers)); + assert( + array_eq( + revertible.new_nullifiers, + [ + Nullifier { value: 30, note_hash: 0, counter: 0 }, + Nullifier { value: 40, note_hash: 0, counter: 0 } + ] + ) + ); assert(array_eq(revertible.public_call_stack, revertible_public_call_stack)); assert_eq( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index 64c95058f83..595a5447529 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -1,7 +1,6 @@ use crate::{ abis::read_request::ReadRequestContext, address::AztecAddress, - abis::side_effect::{Ordered, OrderedValue, Readable}, - constants::{NOTE_HASH_LENGTH, NOTE_HASH_CONTEXT_LENGTH}, hash::silo_note_hash, + abis::side_effect::{Ordered, Readable}, constants::{NOTE_HASH_LENGTH, NOTE_HASH_CONTEXT_LENGTH}, traits::{Empty, Serialize, Deserialize} }; use dep::std::cmp::Eq; @@ -11,21 +10,6 @@ struct NoteHash { counter: u32, } -impl Ordered for NoteHash { - fn counter(self) -> u32 { - self.counter - } -} - -impl OrderedValue for NoteHash { - fn value(self) -> Field { - self.value - } - fn counter(self) -> u32 { - self.counter - } -} - impl Eq for NoteHash { fn eq(self, other: NoteHash) -> bool { (self.value == other.value) @@ -58,8 +42,8 @@ impl Deserialize for NoteHash { } impl NoteHash { - pub fn to_context(self, nullifier_counter: u32) -> NoteHashContext { - NoteHashContext { value: self.value, counter: self.counter, nullifier_counter } + pub fn to_context(self, nullifier_counter: u32, contract_address: AztecAddress) -> NoteHashContext { + NoteHashContext { value: self.value, counter: self.counter, nullifier_counter, contract_address } } } @@ -67,6 +51,7 @@ struct NoteHashContext { value: Field, counter: u32, nullifier_counter: u32, + contract_address: AztecAddress, } impl Ordered for NoteHashContext { @@ -75,20 +60,12 @@ impl Ordered for NoteHashContext { } } -impl OrderedValue for NoteHashContext { - fn value(self) -> Field { - self.value - } - fn counter(self) -> u32 { - self.counter - } -} - impl Eq for NoteHashContext { fn eq(self, other: NoteHashContext) -> bool { (self.value == other.value) & (self.counter == other.counter) & (self.nullifier_counter == other.nullifier_counter) + & (self.contract_address == other.contract_address) } } @@ -98,13 +75,14 @@ impl Empty for NoteHashContext { value: 0, counter: 0, nullifier_counter: 0, + contract_address: AztecAddress::zero(), } } } impl Serialize for NoteHashContext { fn serialize(self) -> [Field; NOTE_HASH_CONTEXT_LENGTH] { - [self.value, self.counter as Field, self.nullifier_counter as Field] + [self.value, self.counter as Field, self.nullifier_counter as Field, self.contract_address.to_field()] } } @@ -114,15 +92,15 @@ impl Deserialize for NoteHashContext { value: values[0], counter: values[1] as u32, nullifier_counter: values[2] as u32, + contract_address: AztecAddress::from_field(values[3]), } } } impl Readable for NoteHashContext { fn assert_match_read_request(self, read_request: ReadRequestContext) { - // TODO(#6122) - let siloed_value = silo_note_hash(read_request.contract_address, read_request.value); - assert_eq(self.value, siloed_value, "Value of the note hash does not match read request"); + assert_eq(self.value, read_request.value, "Value of the note hash does not match read request"); + assert_eq(self.contract_address, read_request.contract_address, "Contract address of the note hash does not match read request"); assert( read_request.counter > self.counter, "Read request counter must be greater than the counter of the note hash" ); @@ -133,10 +111,6 @@ impl Readable for NoteHashContext { } impl NoteHashContext { - pub fn to_note_hash(self) -> NoteHash { - NoteHash { value: self.value, counter: self.counter } - } - pub fn expose_to_public(self) -> NoteHash { // Hide the actual counter when exposing it to the public kernel. NoteHash { value: self.value, counter: 0 } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr index b32a81ee264..cef10ca8fef 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr @@ -1,6 +1,6 @@ use crate::{ - abis::{side_effect::{Ordered, OrderedValue, Readable}, read_request::ReadRequestContext}, - address::AztecAddress, constants::NULLIFIER_LENGTH, hash::silo_nullifier, + abis::{side_effect::{Ordered, OrderedValue, Readable}, read_request::{ReadRequest, ReadRequestContext}}, + address::AztecAddress, constants::{NULLIFIER_CONTEXT_LENGTH, NULLIFIER_LENGTH}, traits::{Empty, Hash, Serialize, Deserialize} }; @@ -10,12 +10,6 @@ struct Nullifier { note_hash: Field, } -impl Ordered for Nullifier { - fn counter(self) -> u32 { - self.counter - } -} - impl OrderedValue for Nullifier { fn value(self) -> Field { self.value @@ -61,10 +55,93 @@ impl Deserialize for Nullifier { impl Readable for Nullifier { fn assert_match_read_request(self, read_request: ReadRequestContext) { - let siloed_value = silo_nullifier(read_request.contract_address, read_request.value); - assert_eq(self.value, siloed_value, "Value of the nullifier does not match read request"); + // Public kernels output Nullifier instead of NullifierContext. + // The value has been siloed in AVM. + assert_eq(self.value, read_request.value, "Value of the nullifier does not match read request"); assert( read_request.counter > self.counter, "Read request counter must be greater than the counter of the nullifier" ); } } + +impl Nullifier { + pub fn to_context(self, contract_address: AztecAddress) -> NullifierContext { + NullifierContext { value: self.value, counter: self.counter, note_hash: self.note_hash, contract_address } + } +} + +struct NullifierContext { + value: Field, + counter: u32, + note_hash: Field, + contract_address: AztecAddress, +} + +impl Ordered for NullifierContext { + fn counter(self) -> u32 { + self.counter + } +} + +impl OrderedValue for NullifierContext { + fn value(self) -> Field { + self.value + } + fn counter(self) -> u32 { + self.counter + } +} + +impl Eq for NullifierContext { + fn eq(self, other: NullifierContext) -> bool { + (self.value == other.value) + & (self.counter == other.counter) + & (self.note_hash == other.note_hash) + & (self.contract_address == other.contract_address) + } +} + +impl Empty for NullifierContext { + fn empty() -> Self { + NullifierContext { + value: 0, + counter: 0, + note_hash: 0, + contract_address: AztecAddress::empty(), + } + } +} + +impl Serialize for NullifierContext { + fn serialize(self) -> [Field; NULLIFIER_CONTEXT_LENGTH] { + [self.value, self.counter as Field, self.note_hash, self.contract_address.to_field()] + } +} + +impl Deserialize for NullifierContext { + fn deserialize(values: [Field; NULLIFIER_CONTEXT_LENGTH]) -> Self { + Self { + value: values[0], + counter: values[1] as u32, + note_hash: values[2], + contract_address: AztecAddress::from_field(values[3]), + } + } +} + +impl Readable for NullifierContext { + fn assert_match_read_request(self, read_request: ReadRequestContext) { + assert_eq(self.value, read_request.value, "Value of the nullifier does not match read request"); + assert_eq(self.contract_address, read_request.contract_address, "Contract address of the nullifier does not match read request"); + assert( + read_request.counter > self.counter, "Read request counter must be greater than the counter of the nullifier" + ); + } +} + +impl NullifierContext { + pub fn expose_to_public(self) -> Nullifier { + // Hide the actual counter and note hash when exposing it to the public kernel. + Nullifier { value: self.value, counter: 0, note_hash: 0 } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index ba2fc9ab0f0..ab4a40540c6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -162,8 +162,9 @@ global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; global READ_REQUEST_LENGTH = 2; global NOTE_HASH_LENGTH = 2; -global NOTE_HASH_CONTEXT_LENGTH = 3; +global NOTE_HASH_CONTEXT_LENGTH = 4; global NULLIFIER_LENGTH = 3; +global NULLIFIER_CONTEXT_LENGTH = 4; global SIDE_EFFECT_LENGTH = 2; global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; global TX_CONTEXT_LENGTH: u64 = 2 + GAS_SETTINGS_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index e0b37375ec6..67430c1781d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -6,7 +6,7 @@ use crate::{ global_variables::GlobalVariables, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, kernel_data::{PrivateKernelData, PublicKernelData, KernelData}, max_block_number::MaxBlockNumber, - note_hash::NoteHashContext, nullifier::Nullifier, + note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::SideEffect, @@ -21,9 +21,9 @@ use crate::{ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::{silo_note_hash, silo_nullifier}, header::Header, - mocked::{AggregationObject, Proof, VerificationKey}, partial_state_reference::PartialStateReference, - tests::fixtures, transaction::tx_context::TxContext, traits::Empty + header::Header, mocked::{AggregationObject, Proof, VerificationKey}, + partial_state_reference::PartialStateReference, tests::fixtures, transaction::tx_context::TxContext, + traits::Empty }; struct FixtureBuilder { @@ -37,7 +37,7 @@ struct FixtureBuilder { // Accumulated data. new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, + new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, @@ -140,8 +140,10 @@ impl FixtureBuilder { pub fn to_public_accumulated_data(self) -> PublicAccumulatedData { PublicAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.to_note_hash()), - new_nullifiers: self.new_nullifiers.storage, + new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| NoteHash { value: n.value, counter: n.counter }), + new_nullifiers: self.new_nullifiers.storage.map( + |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } + ), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, @@ -156,7 +158,7 @@ impl FixtureBuilder { pub fn to_combined_accumulated_data(self) -> CombinedAccumulatedData { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: Nullifier| n.value), + new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, @@ -249,7 +251,14 @@ impl FixtureBuilder { } pub fn add_new_note_hash(&mut self, value: Field) { - self.new_note_hashes.push(NoteHashContext { value, counter: self.next_counter(), nullifier_counter: 0 }); + self.new_note_hashes.push( + NoteHashContext { + value, + counter: self.next_counter(), + nullifier_counter: 0, + contract_address: self.storage_contract_address + } + ); } pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u64) { @@ -257,15 +266,15 @@ impl FixtureBuilder { for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { if i < num_new_note_hashes { let mocked_value = self.get_mocked_note_hash_value(index_offset + i); - let value = silo_note_hash(self.storage_contract_address, mocked_value); - self.add_new_note_hash(value); + self.add_new_note_hash(mocked_value); } } } - pub fn add_nullifier(&mut self, unsiloed_nullifier: Field) { - let value = silo_nullifier(self.storage_contract_address, unsiloed_nullifier); - self.new_nullifiers.push(Nullifier { value, note_hash: 0, counter: self.next_counter() }); + pub fn add_nullifier(&mut self, value: Field) { + self.new_nullifiers.push( + NullifierContext { value, counter: self.next_counter(), note_hash: 0, contract_address: self.storage_contract_address } + ); } pub fn append_new_nullifiers(&mut self, num_extra_nullifier: u64) { @@ -336,22 +345,14 @@ impl FixtureBuilder { pub fn add_read_request_for_pending_nullifier(&mut self, nullifier_index: u64) -> u64 { let read_request_index = self.nullifier_read_requests.len(); - let unsiloed_nullifier = self.get_mocked_nullifier_value(nullifier_index); - let read_request = ReadRequestContext { - value: unsiloed_nullifier, - counter: self.next_counter(), - contract_address: self.storage_contract_address - }; + let nullifier = self.get_mocked_nullifier_value(nullifier_index); + let read_request = ReadRequestContext { value: nullifier, counter: self.next_counter(), contract_address: self.storage_contract_address }; self.nullifier_read_requests.push(read_request); read_request_index } - pub fn add_non_existent_read_request_for_nullifier(&mut self, unsiloed_nullifier: Field) { - let read_request = ReadRequestContext { - value: unsiloed_nullifier, - counter: self.next_counter(), - contract_address: self.storage_contract_address - }; + pub fn add_non_existent_read_request_for_nullifier(&mut self, nullifier: Field) { + let read_request = ReadRequestContext { value: nullifier, counter: self.next_counter(), contract_address: self.storage_contract_address }; self.nullifier_non_existent_read_requests.push(read_request); } From 75933bd291e1a817fd9e9b080069c9fba1cc864d Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Thu, 2 May 2024 20:20:50 +0000 Subject: [PATCH 02/13] Updaet hints. --- .../src/private_kernel_tail.nr | 2 +- .../src/private_kernel_tail_to_public.nr | 2 +- .../src/public_kernel_tail.nr | 6 +- .../src/nullifier_read_request_reset.nr | 9 ++- .../src/reset/non_existent_read_request.nr | 2 +- .../src/reset/transient_data.nr | 22 +++++-- .../crates/types/src/abis/nullifier.nr | 7 ++- .../crates/types/src/abis/read_request.nr | 23 +------ .../crates/types/src/tests/fixture_builder.nr | 17 ++++- ...build_note_hash_read_request_hints.test.ts | 5 +- .../build_note_hash_read_request_hints.ts | 12 ++-- ...build_nullifier_read_request_hints.test.ts | 11 ++-- .../build_nullifier_read_request_hints.ts | 63 +++++++++++++++---- .../hints/build_transient_data_hints.test.ts | 27 +++++--- .../src/hints/build_transient_data_hints.ts | 7 ++- .../kernel/private_accumulated_data.ts | 8 +-- ...vate_kernel_tail_circuit_private_inputs.ts | 10 +-- .../circuits.js/src/structs/note_hash.ts | 32 +++++++--- .../circuits.js/src/structs/nullifier.ts | 45 +++++++++++++ .../circuits.js/src/tests/factories.ts | 9 ++- .../src/type_conversion.ts | 30 +++++++-- .../src/kernel_prover/kernel_prover.test.ts | 9 ++- .../build_private_kernel_tail_hints.ts | 4 +- .../build_private_kernel_tail_outputs.ts | 6 +- .../simulator/src/public/hints_builder.ts | 4 +- 25 files changed, 259 insertions(+), 113 deletions(-) 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 8b3e53f9f10..debab44f900 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 @@ -528,7 +528,7 @@ mod tests { assert_eq(public_inputs.end.gas_used, expected_gas); } - #[test(should_fail_with="Hinted note hash does not match")] + #[test(should_fail_with="Value of the hinted transient note hash does not match")] unconstrained fn wrong_transient_nullifier_index_for_note_hash_fails() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.append_new_note_hashes(1); 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 3806250a683..f2199651053 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 @@ -428,7 +428,7 @@ mod tests { } } - #[test(should_fail_with="Hinted note hash does not match")] + #[test(should_fail_with="Value of the hinted transient note hash does not match")] unconstrained fn wrong_transient_nullifier_index_for_note_hash_fails() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.append_new_note_hashes(1); 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 67b65e16fbc..45ab7205c51 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 @@ -209,19 +209,19 @@ mod tests { } pub fn add_nullifier(&mut self, unsiloed_nullifier: Field) { - self.previous_kernel.add_nullifier(unsiloed_nullifier); + self.previous_kernel.add_siloed_nullifier(unsiloed_nullifier); self.sync_counters(); self.set_nullifiers_for_non_existent_read_request_hints(); } pub fn append_nullifiers_revertible(&mut self, num_nullifiers: u64) { - self.previous_revertible.append_new_nullifiers(num_nullifiers); + self.previous_revertible.append_siloed_nullifiers(num_nullifiers); self.sync_counters(); self.set_nullifiers_for_non_existent_read_request_hints(); } pub fn append_nullifiers_non_revertible(&mut self, num_nullifiers: u64) { - self.previous_kernel.append_new_nullifiers(num_nullifiers); + self.previous_kernel.append_siloed_nullifiers(num_nullifiers); self.sync_counters(); self.set_nullifiers_for_non_existent_read_request_hints(); } 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 47c26125c34..61c315b839a 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 @@ -47,7 +47,10 @@ mod tests { use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ address::AztecAddress, - abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage, read_request::ReadRequestContext}, + abis::{ + nullifier::NullifierContext, nullifier_leaf_preimage::NullifierLeafPreimage, + read_request::ReadRequestContext + }, constants::NULLIFIER_TREE_HEIGHT, hash::silo_nullifier, merkle_tree::MembershipWitness, tests::merkle_tree_utils::NonEmptyMerkleTree }; @@ -68,8 +71,8 @@ mod tests { ]; global pending_values = [ - Nullifier { value: inner_nullifiers[2], counter: 2, note_hash: 0 }, - Nullifier { value: inner_nullifiers[3], counter: 8, note_hash: 0 }, + NullifierContext { value: inner_nullifiers[2], counter: 2, note_hash: 0, contract_address }, + NullifierContext { value: inner_nullifiers[3], counter: 8, note_hash: 0, contract_address }, ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr index afb50e68ce5..10feabce540 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr @@ -91,7 +91,7 @@ mod tests { use dep::types::{ address::AztecAddress, abis::{read_request::ReadRequestContext, side_effect::SideEffect}, merkle_tree::{leaf_preimage::IndexedTreeLeafPreimage, membership::MembershipWitness}, - hash::silo_nullifier, tests::merkle_tree_utils::NonEmptyMerkleTree + tests::merkle_tree_utils::NonEmptyMerkleTree }; struct TestLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index a403f23332a..7287b9ed624 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -18,9 +18,14 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers for Nullifier { impl Readable for Nullifier { fn assert_match_read_request(self, read_request: ReadRequestContext) { // Public kernels output Nullifier instead of NullifierContext. - // The value has been siloed in AVM. - assert_eq(self.value, read_request.value, "Value of the nullifier does not match read request"); + // The nullifier value has been siloed. + let siloed_request_value = silo_nullifier(read_request.contract_address, read_request.value); + assert_eq(self.value, siloed_request_value, "Value of the nullifier does not match read request"); assert( read_request.counter > self.counter, "Read request counter must be greater than the counter of the nullifier" ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr index 7bb0e0ffa42..f0129031bb3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr @@ -1,7 +1,4 @@ -use crate::{ - abis::side_effect::OrderedValue, traits::{Empty, Serialize, Deserialize}, address::AztecAddress, - constants::READ_REQUEST_LENGTH -}; +use crate::{traits::{Empty, Serialize, Deserialize}, address::AztecAddress, constants::READ_REQUEST_LENGTH}; use dep::std::cmp::Eq; global READ_REQUEST_CONTEXT_SERIALIZED_LEN = 3; @@ -11,15 +8,6 @@ struct ReadRequest { counter: u32, } -impl OrderedValue for ReadRequest { - fn value(self) -> Field { - self.value - } - fn counter(self) -> u32 { - self.counter - } -} - impl Eq for ReadRequest { fn eq(self, read_request: ReadRequest) -> bool { (self.value == read_request.value) @@ -63,15 +51,6 @@ struct ReadRequestContext { contract_address: AztecAddress, } -impl OrderedValue for ReadRequestContext { - fn value(self) -> Field { - self.value - } - fn counter(self) -> u32 { - self.counter - } -} - impl Eq for ReadRequestContext { fn eq(self, read_request: ReadRequestContext) -> bool { (self.value == read_request.value) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 67430c1781d..69bf17afcc2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -21,7 +21,7 @@ use crate::{ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - header::Header, mocked::{AggregationObject, Proof, VerificationKey}, + hash::silo_nullifier, header::Header, mocked::{AggregationObject, Proof, VerificationKey}, partial_state_reference::PartialStateReference, tests::fixtures, transaction::tx_context::TxContext, traits::Empty }; @@ -277,6 +277,11 @@ impl FixtureBuilder { ); } + pub fn add_siloed_nullifier(&mut self, value: Field) { + let siloed_value = silo_nullifier(self.storage_contract_address, value); + self.add_nullifier(siloed_value); + } + pub fn append_new_nullifiers(&mut self, num_extra_nullifier: u64) { let index_offset = self.new_nullifiers.len(); for i in 0..MAX_NEW_NULLIFIERS_PER_TX { @@ -287,6 +292,16 @@ impl FixtureBuilder { } } + pub fn append_siloed_nullifiers(&mut self, num_extra_nullifier: u64) { + let index_offset = self.new_nullifiers.len(); + for i in 0..MAX_NEW_NULLIFIERS_PER_TX { + if i < num_extra_nullifier { + let mocked_value = self.get_mocked_nullifier_value(index_offset + i); + self.add_siloed_nullifier(mocked_value); + } + } + } + pub fn add_public_data_update_request(&mut self, leaf_slot: Field, value: Field) { let update_request = PublicDataUpdateRequest { leaf_slot, new_value: value }; self.public_data_update_requests.push(update_request); 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 7c2f508e4fb..86248eb1b9c 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 @@ -38,10 +38,7 @@ describe('buildNoteHashReadRequestHints', () => { const makeReadRequest = (value: number, counter = 2) => new ReadRequestContext(new Fr(value), counter, contractAddress); - function makeNoteHash(value: number, counter = 1) { - const siloedValue = siloNoteHash(contractAddress, new Fr(value)); - return new NoteHashContext(siloedValue, counter, 0); - } + const makeNoteHash = (value: number, counter = 1) => new NoteHashContext(new Fr(value), counter, 0, contractAddress); const readPendingNoteHash = ({ noteHashIndex, 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 0364333d56e..45ea0ea3b98 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 @@ -5,7 +5,6 @@ import { type MAX_NOTE_HASH_READ_REQUESTS_PER_TX, type NOTE_HASH_TREE_HEIGHT, } from '../constants.gen.js'; -import { siloNoteHash } from '../hash/index.js'; import { type MembershipWitness, type NoteHashContext, @@ -15,10 +14,9 @@ import { import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; function isValidNoteHashReadRequest(readRequest: ReadRequestContext, noteHash: NoteHashContext) { - // TODO(#6122) return ( - // noteHash.value.equals(readRequest.value) && - noteHash.counter < readRequest.counter && + noteHash.contractAddress.equals(readRequest.contractAddress) && + readRequest.counter > noteHash.counter && (noteHash.nullifierCounter === 0 || noteHash.nullifierCounter > readRequest.counter) ); } @@ -45,17 +43,15 @@ export async function buildNoteHashReadRequestHints( for (let i = 0; i < numReadRequests; ++i) { const readRequest = noteHashReadRequests[i]; - // TODO(#2847): Read request value shouldn't have been siloed by apps. const value = readRequest.value; - // But reads for transient note hash are not siloed. - const siloedValue = siloNoteHash(readRequest.contractAddress, readRequest.value); const pendingNoteHash = noteHashMap - .get(siloedValue.toBigInt()) + .get(value.toBigInt()) ?.find(n => isValidNoteHashReadRequest(readRequest, n.noteHash)); if (pendingNoteHash !== undefined) { builder.addPendingReadRequest(i, pendingNoteHash.index); } else { + // TODO(#2847): Read request value for settled note hash shouldn't have been siloed by apps. const leafIndex = noteHashLeafIndexMap.get(value.toBigInt()); if (leafIndex === undefined) { throw new Error('Read request is reading an unknown note hash.'); 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 5297a84f5ad..d607f245cc2 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 @@ -4,9 +4,8 @@ import { Fr } from '@aztec/foundation/fields'; import { type Tuple } from '@aztec/foundation/serialize'; import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; -import { siloNullifier } from '../hash/index.js'; import { - Nullifier, + NullifierContext, type NullifierReadRequestHints, NullifierReadRequestHintsBuilder, PendingReadHint, @@ -24,7 +23,7 @@ describe('buildNullifierReadRequestHints', () => { getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; let nullifierReadRequests: Tuple; - let nullifiers: Tuple; + let nullifiers: Tuple; let expectedHints: NullifierReadRequestHints; let numReadRequests = 0; let numPendingReads = 0; @@ -35,10 +34,8 @@ describe('buildNullifierReadRequestHints', () => { const makeReadRequest = (value: number, counter = 2) => new ReadRequestContext(new Fr(value), counter, contractAddress); - function makeNullifier(value: number, counter = 1) { - const siloedValue = siloNullifier(contractAddress, new Fr(value)); - return new Nullifier(siloedValue, counter, Fr.ZERO); - } + const makeNullifier = (value: number, counter = 1) => + new NullifierContext(new Fr(value), counter, Fr.ZERO, contractAddress); const readPendingNullifier = ({ nullifierIndex, 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 3b17bd9d3b5..f56fbf971b9 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 @@ -1,20 +1,23 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { padArrayEnd } from '@aztec/foundation/collection'; import { type Fr } from '@aztec/foundation/fields'; import { type Tuple } from '@aztec/foundation/serialize'; import { type IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { type MAX_NEW_NULLIFIERS_PER_TX, - type MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, type NULLIFIER_TREE_HEIGHT, } from '../constants.gen.js'; -import { siloNullifier } from '../hash/index.js'; +import { siloNullifier } from '../hash/hash.js'; import { type MembershipWitness, type Nullifier, + NullifierContext, NullifierReadRequestHintsBuilder, - type ReadRequestContext, + ReadRequestContext, } from '../structs/index.js'; -import { countAccumulatedItems } from '../utils/index.js'; +import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; interface NullifierMembershipWitnessWithPreimage { membershipWitness: MembershipWitness; @@ -26,25 +29,35 @@ export async function buildNullifierReadRequestHints( getNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, + siloed = false, ) { const builder = new NullifierReadRequestHintsBuilder(); const numReadRequests = countAccumulatedItems(nullifierReadRequests); - const nullifierIndexMap: Map = new Map(); - nullifiers.forEach((n, i) => nullifierIndexMap.set(n.value.toBigInt(), i)); + const nullifierMap: Map = new Map(); + getNonEmptyItems(nullifiers).forEach((nullifier, index) => { + const value = nullifier.value.toBigInt(); + const arr = nullifierMap.get(value) ?? []; + arr.push({ nullifier, index }); + nullifierMap.set(value, arr); + }); for (let i = 0; i < numReadRequests; ++i) { const readRequest = nullifierReadRequests[i]; - // TODO - Should be comparing un-siloed values and contract addresses. - const value = siloNullifier(readRequest.contractAddress, readRequest.value); + const pendingNullifier = nullifierMap + .get(readRequest.value.toBigInt()) + ?.find( + ({ nullifier }) => + nullifier.contractAddress.equals(readRequest.contractAddress) && readRequest.counter > nullifier.counter, + ); - const pendingValueIndex = nullifierIndexMap.get(value.toBigInt()); - if (pendingValueIndex !== undefined) { - builder.addPendingReadRequest(i, pendingValueIndex); + if (pendingNullifier !== undefined) { + builder.addPendingReadRequest(i, pendingNullifier.index); } else { - const membershipWitnessWithPreimage = await oracle.getNullifierMembershipWitness(value); + const siloedValue = siloed ? readRequest.value : siloNullifier(readRequest.contractAddress, readRequest.value); + const membershipWitnessWithPreimage = await oracle.getNullifierMembershipWitness(siloedValue); builder.addSettledReadRequest( i, membershipWitnessWithPreimage.membershipWitness, @@ -54,3 +67,27 @@ export async function buildNullifierReadRequestHints( } return builder.toHints(); } + +export function buildSiloedNullifierReadRequestHints( + oracle: { + getNullifierMembershipWitness(nullifier: Fr): Promise; + }, + nullifierReadRequests: Tuple, + nullifiers: Tuple, +) { + // 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. + const siloedReadRequests = padArrayEnd( + getNonEmptyItems(nullifierReadRequests).map( + r => new ReadRequestContext(siloNullifier(r.contractAddress, r.value), r.counter, AztecAddress.ZERO), + ), + ReadRequestContext.empty(), + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + ); + + const nullifierContexts = nullifiers.map( + n => new NullifierContext(n.value, n.counter, n.noteHash, AztecAddress.ZERO), + ) as Tuple; + + return buildNullifierReadRequestHints(oracle, siloedReadRequests, nullifierContexts, true); +} diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index a0d4e3fee60..27f183ead6e 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -1,22 +1,24 @@ -import { Fr, NoteHashContext, Nullifier } from '@aztec/circuits.js'; +import { AztecAddress, Fr, NoteHashContext, NullifierContext } from '@aztec/circuits.js'; import { buildTransientDataHints } from './build_transient_data_hints.js'; describe('buildTransientDataHints', () => { + const contractAddress = AztecAddress.fromBigInt(987654n); + let noteHashes: NoteHashContext[]; - let nullifiers: Nullifier[]; + let nullifiers: NullifierContext[]; beforeEach(() => { noteHashes = [ - new NoteHashContext(new Fr(11), 100, 700), - new NoteHashContext(new Fr(22), 200, 0), - new NoteHashContext(new Fr(33), 300, 500), + new NoteHashContext(new Fr(11), 100, 700, contractAddress), + new NoteHashContext(new Fr(22), 200, 0, contractAddress), + new NoteHashContext(new Fr(33), 300, 500, contractAddress), ]; nullifiers = [ - new Nullifier(new Fr(44), 400, new Fr(0)), - new Nullifier(new Fr(55), 500, new Fr(33)), - new Nullifier(new Fr(66), 600, new Fr(0)), - new Nullifier(new Fr(77), 700, new Fr(11)), + new NullifierContext(new Fr(44), 400, new Fr(0), contractAddress), + new NullifierContext(new Fr(55), 500, new Fr(33), contractAddress), + new NullifierContext(new Fr(66), 600, new Fr(0), contractAddress), + new NullifierContext(new Fr(77), 700, new Fr(11), contractAddress), ]; }); @@ -35,4 +37,11 @@ describe('buildTransientDataHints', () => { nullifiers[1].noteHash = new Fr(11); expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow('Hinted note hash does not match.'); }); + + it('throws if contract address does not match', () => { + nullifiers[1].contractAddress = AztecAddress.fromBigInt(123456n); + expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow( + 'Contract address of hinted note hash does not match.', + ); + }); }); diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts index bee36948fd7..2ef02973192 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts @@ -1,10 +1,10 @@ -import { type NoteHashContext, type Nullifier, countAccumulatedItems } from '@aztec/circuits.js'; +import { type NoteHashContext, type NullifierContext, countAccumulatedItems } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildTransientDataHints( noteHashes: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, noteHashesLength: NOTE_HASHES_LEN = noteHashes.length as NOTE_HASHES_LEN, nullifiersLength: NULLIFIERS_LEN = nullifiers.length as NULLIFIERS_LEN, ): [Tuple, Tuple] { @@ -34,6 +34,9 @@ export function buildTransientDataHints, + public newNullifiers: Tuple, /** * All the new L2 to L1 messages created in this transaction. */ @@ -91,7 +91,7 @@ export class PrivateAccumulatedData { const reader = BufferReader.asReader(buffer); return new PrivateAccumulatedData( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), @@ -114,7 +114,7 @@ export class PrivateAccumulatedData { static empty() { return new PrivateAccumulatedData( makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty), + makeTuple(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index 8fa1de2c2ac..e9d6155a44d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -11,7 +11,7 @@ import { import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; import { NoteHashContext } from '../note_hash.js'; -import { Nullifier } from '../nullifier.js'; +import { NullifierContext } from '../nullifier.js'; import { type NoteHashReadRequestHints, type NullifierReadRequestHints, @@ -24,7 +24,7 @@ import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelTailOutputs { constructor( public noteHashes: Tuple, - public nullifiers: Tuple, + public nullifiers: Tuple, ) {} toBuffer() { @@ -35,7 +35,7 @@ export class PrivateKernelTailOutputs { const reader = BufferReader.asReader(buffer); return new PrivateKernelTailOutputs( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), ); } } @@ -74,7 +74,7 @@ export class PrivateKernelTailHints { /** * The sorted new nullifiers. Maps original to sorted. */ - public sortedNewNullifiers: Tuple, + public sortedNewNullifiers: Tuple, /** * The sorted new nullifiers indexes. */ @@ -130,7 +130,7 @@ export class PrivateKernelTailHints { reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), reader.readNumbers(MAX_ENCRYPTED_LOGS_PER_TX), diff --git a/yarn-project/circuits.js/src/structs/note_hash.ts b/yarn-project/circuits.js/src/structs/note_hash.ts index dfe63e8c720..ac4f9acee20 100644 --- a/yarn-project/circuits.js/src/structs/note_hash.ts +++ b/yarn-project/circuits.js/src/structs/note_hash.ts @@ -1,3 +1,4 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -38,35 +39,50 @@ export class NoteHash { } export class NoteHashContext implements Ordered { - constructor(public value: Fr, public counter: number, public nullifierCounter: number) {} + constructor( + public value: Fr, + public counter: number, + public nullifierCounter: number, + public contractAddress: AztecAddress, + ) {} toFields(): Fr[] { - return [this.value, new Fr(this.counter), new Fr(this.nullifierCounter)]; + return [this.value, new Fr(this.counter), new Fr(this.nullifierCounter), this.contractAddress.toField()]; } static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new NoteHashContext(reader.readField(), reader.readU32(), reader.readU32()); + return new NoteHashContext( + reader.readField(), + reader.readU32(), + reader.readU32(), + AztecAddress.fromField(reader.readField()), + ); } isEmpty() { - return this.value.isZero() && !this.counter && !this.nullifierCounter; + return this.value.isZero() && !this.counter && !this.nullifierCounter && this.contractAddress.isZero(); } static empty() { - return new NoteHashContext(Fr.zero(), 0, 0); + return new NoteHashContext(Fr.zero(), 0, 0, AztecAddress.ZERO); } toBuffer(): Buffer { - return serializeToBuffer(this.value, this.counter, this.nullifierCounter); + return serializeToBuffer(this.value, this.counter, this.nullifierCounter, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new NoteHashContext(Fr.fromBuffer(reader), reader.readNumber(), reader.readNumber()); + return new NoteHashContext( + Fr.fromBuffer(reader), + reader.readNumber(), + reader.readNumber(), + AztecAddress.fromBuffer(reader), + ); } toString(): string { - return `value=${this.value} counter=${this.counter} nullifierCounter=${this.nullifierCounter}`; + return `value=${this.value} counter=${this.counter} nullifierCounter=${this.nullifierCounter} contractAddress=${this.contractAddress}`; } } diff --git a/yarn-project/circuits.js/src/structs/nullifier.ts b/yarn-project/circuits.js/src/structs/nullifier.ts index 176628d5e1d..fd2fd126396 100644 --- a/yarn-project/circuits.js/src/structs/nullifier.ts +++ b/yarn-project/circuits.js/src/structs/nullifier.ts @@ -1,3 +1,4 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -36,3 +37,47 @@ export class Nullifier implements Ordered { return `value=${this.value} counter=${this.counter} noteHash=${this.noteHash}`; } } + +export class NullifierContext implements Ordered { + constructor(public value: Fr, public counter: number, public noteHash: Fr, public contractAddress: AztecAddress) {} + + toFields(): Fr[] { + return [this.value, new Fr(this.counter), this.noteHash, this.contractAddress.toField()]; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new NullifierContext( + reader.readField(), + reader.readU32(), + reader.readField(), + AztecAddress.fromField(reader.readField()), + ); + } + + isEmpty() { + return this.value.isZero() && !this.counter && this.noteHash.isZero() && this.contractAddress.isZero(); + } + + static empty() { + return new NullifierContext(Fr.zero(), 0, Fr.zero(), AztecAddress.ZERO); + } + + toBuffer(): Buffer { + return serializeToBuffer(this.value, this.counter, this.noteHash, this.contractAddress); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new NullifierContext( + Fr.fromBuffer(reader), + reader.readNumber(), + Fr.fromBuffer(reader), + AztecAddress.fromBuffer(reader), + ); + } + + toString(): string { + return `value=${this.value} counter=${this.counter} noteHash=${this.noteHash} contractAddress=${this.contractAddress}`; + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 7236227a991..3401439d0f6 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -77,6 +77,7 @@ import { NoteHash, NoteHashContext, Nullifier, + NullifierContext, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, NullifierLeafPreimage, @@ -161,13 +162,17 @@ function makeNoteHash(seed: number) { } function makeNoteHashContext(seed: number) { - return new NoteHashContext(fr(seed), seed + 1, seed + 2); + return new NoteHashContext(fr(seed), seed + 1, seed + 2, makeAztecAddress(seed + 3)); } function makeNullifier(seed: number) { return new Nullifier(fr(seed), seed + 1, fr(seed + 2)); } +function makeNullifierContext(seed: number) { + return new NullifierContext(fr(seed), seed + 1, fr(seed + 2), makeAztecAddress(seed + 3)); +} + /** * Creates an arbitrary tx context with the given seed. * @param seed - The seed to use for generating the tx context. @@ -367,7 +372,7 @@ export function makePrivateAccumulatedData(seed = 1, full = false) { return new PrivateAccumulatedData( tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHashContext, seed + 0x120, NoteHashContext.empty), - tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, makeNullifier, seed + 0x200, Nullifier.empty), + tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, makeNullifierContext, seed + 0x200, NullifierContext.empty), tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x700, SideEffect.empty), // encrypted logs hashes tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x800, SideEffect.empty), // unencrypted logs hashes 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 fa9aa79f014..d27388e3237 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -56,6 +56,7 @@ import { NoteHashContext, type NoteHashReadRequestHints, Nullifier, + NullifierContext, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, type NullifierLeafPreimage, @@ -142,6 +143,7 @@ import { type GrumpkinPoint as NoirPoint, type NoteHashContext as NoteHashContextNoir, type NoteHash as NoteHashNoir, + type NullifierContext as NullifierContextNoir, type NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, type NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, type Nullifier as NullifierNoir, @@ -560,6 +562,7 @@ function mapNoteHashContextToNoir(noteHash: NoteHashContext): NoteHashContextNoi value: mapFieldToNoir(noteHash.value), counter: mapNumberToNoir(noteHash.counter), nullifier_counter: mapNumberToNoir(noteHash.nullifierCounter), + contract_address: mapAztecAddressToNoir(noteHash.contractAddress), }; } @@ -568,6 +571,7 @@ function mapNoteHashContextFromNoir(noteHash: NoteHashContextNoir) { mapFieldFromNoir(noteHash.value), mapNumberFromNoir(noteHash.counter), mapNumberFromNoir(noteHash.nullifier_counter), + mapAztecAddressFromNoir(noteHash.contract_address), ); } @@ -587,6 +591,24 @@ function mapNullifierFromNoir(nullifier: NullifierNoir) { ); } +function mapNullifierContextToNoir(nullifier: NullifierContext): NullifierContextNoir { + return { + value: mapFieldToNoir(nullifier.value), + counter: mapNumberToNoir(nullifier.counter), + note_hash: mapFieldToNoir(nullifier.noteHash), + contract_address: mapAztecAddressToNoir(nullifier.contractAddress), + }; +} + +function mapNullifierContextFromNoir(nullifier: NullifierContextNoir) { + return new NullifierContext( + mapFieldFromNoir(nullifier.value), + mapNumberFromNoir(nullifier.counter), + mapFieldFromNoir(nullifier.note_hash), + mapAztecAddressFromNoir(nullifier.contract_address), + ); +} + /** * Maps a SideEffect to a noir side effect. * @param sideEffect - The SideEffect. @@ -1048,7 +1070,7 @@ export function mapPrivateAccumulatedDataFromNoir( ): PrivateAccumulatedData { return new PrivateAccumulatedData( mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapNoteHashContextFromNoir), - mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierFromNoir), + mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierContextFromNoir), mapTupleFromNoir(privateAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), mapTupleFromNoir(privateAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir( @@ -1074,7 +1096,7 @@ export function mapPrivateAccumulatedDataFromNoir( export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): PrivateAccumulatedDataNoir { return { new_note_hashes: mapTuple(data.newNoteHashes, mapNoteHashContextToNoir), - new_nullifiers: mapTuple(data.newNullifiers, mapNullifierToNoir), + new_nullifiers: mapTuple(data.newNullifiers, mapNullifierContextToNoir), new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapFieldToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapSideEffectToNoir), @@ -1408,7 +1430,7 @@ export function mapPrivateKernelInnerCircuitPrivateInputsToNoir( function mapPrivateKernelTailOutputsToNoir(inputs: PrivateKernelTailOutputs): PrivateKernelTailOutputsNoir { return { note_hashes: mapTuple(inputs.noteHashes, mapNoteHashContextToNoir), - nullifiers: mapTuple(inputs.nullifiers, mapNullifierToNoir), + nullifiers: mapTuple(inputs.nullifiers, mapNullifierContextToNoir), }; } @@ -1424,7 +1446,7 @@ function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): Privat master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapNoteHashContextToNoir), sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), - sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapNullifierToNoir), + sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapNullifierContextToNoir), sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapSideEffectToNoir), sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index 0f41bace642..698b6625afa 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -35,6 +35,8 @@ describe('Kernel Prover', () => { let prover: KernelProver; let dependencies: { [name: string]: string[] } = {}; + const contractAddress = AztecAddress.fromBigInt(987654n); + const notesAndSlots: NoteAndSlot[] = Array(10) .fill(null) .map(() => ({ @@ -80,7 +82,12 @@ describe('Kernel Prover', () => { const publicInputs = PrivateKernelCircuitPublicInputs.empty(); const noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext.empty); for (let i = 0; i < newNoteIndices.length; i++) { - noteHashes[i] = new NoteHashContext(generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]), 0, 0); + noteHashes[i] = new NoteHashContext( + generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]), + 0, + 0, + contractAddress, + ); } publicInputs.end.newNoteHashes = noteHashes; diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index ffa4eef1b9d..13651f02924 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -9,7 +9,7 @@ import { type MAX_UNENCRYPTED_LOGS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, - type Nullifier, + type NullifierContext, type NullifierKeyValidationRequestContext, type PrivateKernelCircuitPublicInputs, PrivateKernelTailHints, @@ -50,7 +50,7 @@ function sortSideEffects( function getNullifierReadRequestHints( nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, oracle: ProvingDataOracle, ) { const getNullifierMembershipWitness = async (nullifier: Fr) => { diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts index ab2594b7b62..7ced5fa6fb6 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts @@ -2,7 +2,7 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NoteHashContext, - Nullifier, + NullifierContext, PrivateKernelTailOutputs, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -10,7 +10,7 @@ import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelTailOutputs( prevNoteHashes: Tuple, - prevNullifiers: Tuple, + prevNullifiers: Tuple, ) { // Propagate note hashes that are not linked to a nullifier. // Note that note hashes can't link to the first nullifier (counter == 0). @@ -22,7 +22,7 @@ export function buildPrivateKernelTailOutputs( const nullifiers = padArrayEnd( prevNullifiers.filter(n => n.noteHash.isZero()), - Nullifier.empty(), + NullifierContext.empty(), MAX_NEW_NULLIFIERS_PER_TX, ); diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index b0cb14e33fb..f88af9b87b0 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -17,9 +17,9 @@ import { type PublicDataUpdateRequest, type ReadRequestContext, buildNullifierNonExistentReadRequestHints, - buildNullifierReadRequestHints, buildPublicDataHints, buildPublicDataReadRequestHints, + buildSiloedNullifierReadRequestHints, } from '@aztec/circuits.js'; import { type Tuple } from '@aztec/foundation/serialize'; import { type IndexedTreeId, type MerkleTreeOperations } from '@aztec/world-state'; @@ -31,7 +31,7 @@ export class HintsBuilder { nullifierReadRequests: Tuple, pendingNullifiers: Tuple, ) { - return buildNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers); + return buildSiloedNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers); } getNullifierNonExistentReadRequestHints( From ed05ef34fcee9c04ac17c0b43ead6b54e9afe03e Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Fri, 3 May 2024 22:55:04 +0000 Subject: [PATCH 03/13] Add counter to l2-l1 msg. Silo in tail. --- .../src/core/libraries/ConstantsGen.sol | 6 +- .../aztec/src/context/private_context.nr | 49 ++++++------- .../aztec/src/context/public_context.nr | 28 ++++---- .../kernel_circuit_public_inputs_composer.nr | 24 ++++++- ...e_kernel_circuit_public_inputs_composer.nr | 11 +-- .../src/private_kernel_init.nr | 2 +- .../src/private_kernel_inner.nr | 2 +- .../src/public_kernel_app_logic.nr | 4 +- .../private_accumulated_data.nr | 5 +- .../private_accumulated_data_builder.nr | 40 +++++++++-- .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 2 +- .../types/src/abis/public_call_stack_item.nr | 4 +- .../src/abis/public_circuit_public_inputs.nr | 2 +- .../crates/types/src/constants.nr | 3 +- .../crates/types/src/hash.nr | 2 +- .../types/src/messaging/l2_to_l1_message.nr | 58 +++++++++++++++- .../crates/types/src/tests/fixture_builder.nr | 24 +++++-- .../crates/types/src/utils/arrays.nr | 27 ++++++++ yarn-project/circuits.js/src/constants.gen.ts | 6 +- .../kernel/private_accumulated_data.ts | 7 +- .../src/structs/l2_to_l1_message.ts | 44 +++++++++--- .../circuits.js/src/tests/factories.ts | 68 +------------------ .../src/type_conversion.ts | 26 ++++++- .../simulator/src/avm/journal/journal.test.ts | 8 +-- .../simulator/src/avm/journal/journal.ts | 2 +- .../src/avm/opcodes/accrued_substate.test.ts | 4 +- .../simulator/src/public/index.test.ts | 7 +- .../src/public/transitional_adaptors.ts | 3 +- 29 files changed, 290 insertions(+), 180 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 3e5ec74866d..cd69c16d714 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -115,15 +115,17 @@ library Constants { uint256 internal constant GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH; uint256 internal constant APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 6; - uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 2; + uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 3; + uint256 internal constant SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; uint256 internal constant NOTE_HASH_LENGTH = 2; - uint256 internal constant NOTE_HASH_CONTEXT_LENGTH = 3; + uint256 internal constant NOTE_HASH_CONTEXT_LENGTH = 4; uint256 internal constant NULLIFIER_LENGTH = 3; + uint256 internal constant NULLIFIER_CONTEXT_LENGTH = 4; uint256 internal constant SIDE_EFFECT_LENGTH = 2; uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index b5d5621bd10..3027613610b 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -97,13 +97,11 @@ impl ContextInterface for PrivateContext { } fn push_new_note_hash(&mut self, note_hash: Field) { - self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.side_effect_counter }); - self.side_effect_counter = self.side_effect_counter + 1; + self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() }); } fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) { - self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.side_effect_counter }); - self.side_effect_counter = self.side_effect_counter + 1; + self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() }); } } @@ -192,15 +190,13 @@ impl PrivateContext { } pub fn push_note_hash_read_request(&mut self, note_hash: Field) { - let side_effect = ReadRequest { value: note_hash, counter: self.side_effect_counter }; + let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() }; self.note_hash_read_requests.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; } pub fn push_nullifier_read_request(&mut self, nullifier: Field) { - let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; + let request = ReadRequest { value: nullifier, counter: self.next_counter() }; self.nullifier_read_requests.push(request); - self.side_effect_counter = self.side_effect_counter + 1; } pub fn request_app_nullifier_secret_key(&mut self, account: AztecAddress) -> Field { @@ -226,7 +222,7 @@ impl PrivateContext { // docs:start:context_message_portal pub fn message_portal(&mut self, recipient: EthAddress, content: Field) { // docs:end:context_message_portal - let message = L2ToL1Message { recipient, content }; + let message = L2ToL1Message { recipient, content, counter: self.next_counter() }; self.new_l2_to_l1_msgs.push(message); } @@ -257,14 +253,9 @@ impl PrivateContext { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); let log_slice = log.to_be_bytes_arr(); - let log_hash = compute_unencrypted_log_hash( - contract_address, - event_selector, - log, - ); - let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log); + let side_effect = SideEffect { value: log_hash, counter: self.next_counter() }; self.unencrypted_logs_hashes.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) self.unencrypted_log_preimages_length += 44 + log_slice.len().to_field(); // call oracle @@ -281,15 +272,10 @@ impl PrivateContext { pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); - let log_hash = emit_contract_class_unencrypted_log_private_internal( - contract_address, - event_selector, - log, - self.side_effect_counter - ); - let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + let counter = self.next_counter(); + let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); + let side_effect = SideEffect { value: log_hash, counter }; self.unencrypted_logs_hashes.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) self.unencrypted_log_preimages_length += 44 + N*32; } @@ -304,19 +290,19 @@ impl PrivateContext { ) where [Field; N]: LensForEncryptedLog { // TODO(1139): perform encryption in the circuit // The oracle call should come last, but we require the encrypted value for now + let counter = self.next_counter(); let encrypted_log: [Field; M] = emit_encrypted_log( contract_address, storage_slot, note_type_id, encryption_pub_key, preimage, - self.side_effect_counter + counter ); let log_hash = compute_encrypted_log_hash(encrypted_log); - let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + let side_effect = SideEffect { value: log_hash, counter }; self.encrypted_logs_hashes.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; - let encrypted_log_byte_len = 112 + 32*(N + 3); + let encrypted_log_byte_len = 112 + 32 * (N + 3); // + processed log len (4) self.encrypted_log_preimages_length += encrypted_log_byte_len + 4; } @@ -580,6 +566,12 @@ impl PrivateContext { self.public_call_stack_hashes.push(item.hash()); } + + fn next_counter(&mut self) -> u32 { + let counter = self.side_effect_counter; + self.side_effect_counter += 1; + counter + } } impl Empty for PrivateContext { @@ -663,7 +655,6 @@ fn emit_contract_class_unencrypted_log_private( counter: u32 ) -> Field {} - unconstrained pub fn emit_contract_class_unencrypted_log_private_internal( contract_address: AztecAddress, event_selector: Field, diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 33765f8f3ec..a13bf5823ab 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -72,7 +72,7 @@ impl PublicContext { unencrypted_logs_hashes: BoundedVec::new(), unencrypted_log_preimages_length: 0, historical_header: inputs.historical_header, - prover_address: AztecAddress::zero(), + prover_address: AztecAddress::zero() } } @@ -131,20 +131,17 @@ impl PublicContext { // Keep private or ask the AVM team if you want to change it. fn push_nullifier_read_request(&mut self, nullifier: Field) { - let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; + let request = ReadRequest { value: nullifier, counter: self.next_counter() }; self.nullifier_read_requests.push(request); - self.side_effect_counter = self.side_effect_counter + 1; } // Keep private or ask the AVM team if you want to change it. fn push_nullifier_non_existent_read_request(&mut self, nullifier: Field) { - let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; + let request = ReadRequest { value: nullifier, counter: self.next_counter() }; self.nullifier_non_existent_read_requests.push(request); - self.side_effect_counter = self.side_effect_counter + 1; } pub fn finish(self) -> PublicCircuitPublicInputs { - // Compute the public call stack hashes let pub_circuit_pub_inputs = PublicCircuitPublicInputs { call_context: self.inputs.call_context, // Done @@ -172,6 +169,12 @@ impl PublicContext { }; pub_circuit_pub_inputs } + + fn next_counter(&mut self) -> u32 { + let counter = self.side_effect_counter; + self.side_effect_counter += 1; + counter + } } impl ContextInterface for PublicContext { @@ -200,17 +203,15 @@ impl ContextInterface for PublicContext { } fn push_new_note_hash(&mut self, note_hash: Field) { - self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.side_effect_counter }); - self.side_effect_counter = self.side_effect_counter + 1; + self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() }); } fn push_new_nullifier(&mut self, nullifier: Field, _nullified_note_hash: Field) { self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: 0, // cannot nullify pending notes in public context - counter: self.side_effect_counter + counter: self.next_counter() }); - self.side_effect_counter = self.side_effect_counter + 1; } } @@ -246,7 +247,7 @@ impl PublicContextInterface for PublicContext { } fn message_portal(&mut self, recipient: EthAddress, content: Field) { - let message = L2ToL1Message { recipient, content }; + let message = L2ToL1Message { recipient, content, counter: self.next_counter() }; self.new_l2_to_l1_msgs.push(message); } @@ -278,9 +279,8 @@ impl PublicContextInterface for PublicContext { event_selector, log ); - let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + let side_effect = SideEffect { value: log_hash, counter: self.next_counter() }; self.unencrypted_logs_hashes.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) self.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length + 44 + log_slice.len().to_field(); // Call oracle to broadcast log @@ -354,7 +354,7 @@ fn emit_unencrypted_log_oracle( _contract_address: AztecAddress, _event_selector: Field, _message: T, - _counter: u32, + _counter: u32 ) -> Field {} struct FunctionReturns { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index db62d9084fd..8a3a6717e01 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -10,7 +10,10 @@ use dep::types::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, silo_note_hash, silo_nullifier}, + hash::{ + compute_l2_to_l1_hash, compute_note_hash_nonce, compute_unique_siloed_note_hash, silo_note_hash, + silo_nullifier +}, utils::arrays::{array_length, array_to_bounded_vec, assert_sorted_array} }; @@ -124,7 +127,7 @@ impl KernelCircuitPublicInputsComposer { fn silo_values(&mut self) { self.silo_note_hashes(); self.silo_nullifiers(); - // TODO: Move siloing from init/inner circuits to here. + self.silo_l2_to_l1_messages(); } fn silo_note_hashes(&mut self) { @@ -154,6 +157,23 @@ impl KernelCircuitPublicInputsComposer { } } + fn silo_l2_to_l1_messages(&mut self) { + let l2_to_l1_msgs = self.public_inputs.end.new_l2_to_l1_msgs.storage; + let tx_context = self.previous_kernel.public_inputs.constants.tx_context; + for i in 0..l2_to_l1_msgs.len() { + let msg = l2_to_l1_msgs[i]; + if !msg.contract_address.is_zero() { + let siloed = compute_l2_to_l1_hash( + msg.contract_address, + tx_context.version, + tx_context.chain_id, + msg.value + ); + self.public_inputs.end.new_l2_to_l1_msgs.storage[i].value.content = siloed; + } + } + } + fn propagate_rollup_validation_requests(&mut self) { self.public_inputs.validation_requests.max_block_number = self.previous_kernel.public_inputs.validation_requests.for_rollup.max_block_number; } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index c474d2ce756..b1c1860b66a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -10,8 +10,7 @@ use dep::types::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL }, - hash::compute_l2_to_l1_hash, traits::is_empty, transaction::tx_request::TxRequest, - utils::arrays::array_to_bounded_vec + traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::array_to_bounded_vec }; struct DataSource { @@ -174,13 +173,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..l2_to_l1_msgs.len() { let msg = l2_to_l1_msgs[i]; if !is_empty(msg) { - let hash = compute_l2_to_l1_hash( - source.storage_contract_address, - source.private_call_public_inputs.tx_context.version, - source.private_call_public_inputs.tx_context.chain_id, - msg - ); - self.public_inputs.end.new_l2_to_l1_msgs.push(hash); + self.public_inputs.end.new_l2_to_l1_msgs.push(msg.scope(source.storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 769e5021dff..a795d4578b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -232,7 +232,7 @@ mod tests { builder.private_call.public_inputs.new_l2_to_l1_msgs.extend_from_array( [ L2ToL1Message::empty(), - L2ToL1Message { recipient: EthAddress::from_field(6), content: 9123 } + L2ToL1Message { recipient: EthAddress::from_field(6), content: 9123, counter: 0 } ] ); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 911a5c63c0c..2af895bb398 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -451,7 +451,7 @@ mod tests { builder.private_call.public_inputs.new_l2_to_l1_msgs.extend_from_array( [ L2ToL1Message::empty(), - L2ToL1Message { recipient: EthAddress::from_field(6), content: 888 } + L2ToL1Message { recipient: EthAddress::from_field(6), content: 888, counter: 0 } ] ); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index f51fcc03f35..0e0b753956d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -281,9 +281,9 @@ mod tests { // Setup 1 new l2 to l1 message on the previous kernel. let previous = [12345]; - builder.previous_kernel.new_l2_to_l1_msgs.extend_from_array(previous); + builder.previous_kernel.add_l2_to_l1_message(previous[0], portal_contract_address); // Setup 1 new l2 to l1 message on the current public inputs. - let current = [L2ToL1Message { recipient: portal_contract_address, content: 67890 }]; + let current = [L2ToL1Message { recipient: portal_contract_address, content: 67890, counter: 0 }]; builder.public_call.public_inputs.new_l2_to_l1_msgs.extend_from_array(current); let tx_context = builder.previous_kernel.tx_context; let version = tx_context.version; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 31f9d29d9d0..14d53d9437b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -2,7 +2,8 @@ use crate::{ abis::{ call_request::CallRequest, gas::Gas, note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect -} +}, + messaging::l2_to_l1_message::ScopedL2ToL1Message }; use crate::constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, @@ -13,7 +14,7 @@ use crate::constants::{ struct PrivateAccumulatedData { new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + new_l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_TX], encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index d4e929809c7..037cf8c06d1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -16,7 +16,7 @@ use crate::{ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE }, - traits::{Empty, is_empty} + messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Empty, is_empty} }; // Builds via PrivateKernelCircuitPublicInputsBuilder: @@ -26,7 +26,7 @@ use crate::{ struct PrivateAccumulatedDataBuilder { new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, @@ -65,7 +65,7 @@ impl PrivateAccumulatedDataBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), encrypted_logs_hash, unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -153,6 +153,15 @@ impl PrivateAccumulatedDataBuilder { } } + for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { + let msg = self.new_l2_to_l1_msgs.storage[i]; + if msg.value.counter < min_revertible_side_effect_counter { + non_revertible_builder.new_l2_to_l1_msgs.push(msg.value.content); + } else { + revertible_builder.new_l2_to_l1_msgs.push(msg.value.content); + } + } + // TODO(gas): add AVM_STARTUP_L2_GAS here for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { let call_stack_item = self.public_call_stack.storage[i]; @@ -181,7 +190,6 @@ impl PrivateAccumulatedDataBuilder { } } - revertible_builder.new_l2_to_l1_msgs = self.new_l2_to_l1_msgs; // TODO(1641) & TODO(4712): Once we track logs with more info, including individual lens, split here revertible_builder.encrypted_log_preimages_length = self.encrypted_log_preimages_length; revertible_builder.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length; @@ -202,13 +210,18 @@ mod tests { note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, - address::AztecAddress, utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} + address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, + utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} }; #[test] unconstrained fn splits_revertible_and_non_revertible() { let mut builder = PrivateAccumulatedDataBuilder::empty(); + let min_revertible_side_effect_counter = 7; + + // Non revertible: counter < 7 + let non_revertible_note_hashes = [ NoteHashContext { value: 1, counter: 1, nullifier_counter: 20, contract_address: AztecAddress::from_field(7788) }, NoteHashContext { value: 2, counter: 3, nullifier_counter: 5, contract_address: AztecAddress::from_field(5566) } @@ -219,6 +232,10 @@ mod tests { NullifierContext { value: 20, note_hash: 2, counter: 4, contract_address: AztecAddress::from_field(7788) } ]; + let non_revertible_l2_to_l1_messages = [ + L2ToL1Message { recipient: EthAddress::from_field(3030), content: 333333, counter: 5 }.scope(AztecAddress::from_field(9900)) + ]; + let non_revertible_public_stack = [ CallRequest { hash: 1, @@ -236,6 +253,8 @@ mod tests { } ]; + // Revertible: counter >= 7 + let revertible_note_hashes = [ NoteHashContext { value: 3, counter: 7, nullifier_counter: 15, contract_address: AztecAddress::from_field(9900) }, NoteHashContext { value: 4, counter: 10, nullifier_counter: 0, contract_address: AztecAddress::from_field(7788) } @@ -246,6 +265,10 @@ mod tests { NullifierContext { value: 40, note_hash: 4, counter: 11, contract_address: AztecAddress::from_field(5566) } ]; + let revertible_l2_to_l1_messages = [ + L2ToL1Message { recipient: EthAddress::from_field(3030), content: 444444, counter: 13 }.scope(AztecAddress::from_field(7788)) + ]; + let revertible_public_call_stack = [ CallRequest { hash: 3, @@ -262,10 +285,13 @@ mod tests { builder.new_nullifiers.extend_from_array(non_revertible_nullifiers); builder.new_nullifiers.extend_from_array(revertible_nullifiers); + builder.new_l2_to_l1_msgs.extend_from_array(non_revertible_l2_to_l1_messages); + builder.new_l2_to_l1_msgs.extend_from_array(revertible_l2_to_l1_messages); + builder.public_call_stack.extend_from_array(non_revertible_public_stack); builder.public_call_stack.extend_from_array(revertible_public_call_stack); - let (non_revertible, revertible) = builder.split_to_public(7, Gas::new(42, 17)); + let (non_revertible, revertible) = builder.split_to_public(min_revertible_side_effect_counter, Gas::new(42, 17)); assert( array_eq( @@ -285,6 +311,7 @@ mod tests { ] ) ); + assert(array_eq(non_revertible.new_l2_to_l1_msgs, [333333])); assert(array_eq(non_revertible.public_call_stack, non_revertible_public_stack)); assert( @@ -305,6 +332,7 @@ mod tests { ] ) ); + assert(array_eq(revertible.new_l2_to_l1_msgs, [444444])); assert(array_eq(revertible.public_call_stack, revertible_public_call_stack)); assert_eq( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 7fc8c7a86c0..18932fc000f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x17fd6ffcb3394b845069dc87e055c37ac50599f274130fac69c6fe919bfe382e; + let test_data_empty_hash = 0x0700e78957e211c160928fab8448fc9b738b08ce880412e433eb4bcf3c1093c7; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index e4dc6851f99..777b1938148 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -211,6 +211,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x29129c06414f4ac73bf889692c7011f91727d4cdbfe4fe143e6adee69b565cc8; + let test_data_empty_hash = 0x1c397d7bced95ebd2725a5c33ed11c065ef84ab72a98d085453fe7c3d7af9b28; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index bdd3aa1c570..8c24533dd6b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x1595b195f0faa3a492109039dc807b291d0edd81a5e3a380866d5098ffd505dd; + let test_data_call_stack_item_request_hash = 0x1177a69fbc37f0ebdf290025414ff72504497840f174896bd427d0f30ec21c55; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x1122a7d7e6174b7e5d111c8eb0233564d3a1ffd755afc7ce4b594d738e2770d7; + let test_data_call_stack_item_hash = 0x0f7624c0d5ea65fcec318c4d34cb3fcbf9c67435aebbf1548b3c90ef641424f8; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index 41fadb37de3..aafdd024ec8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -195,6 +195,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x1a2da219bb2e3ac24519fd844365c4f656fc3ba8c58f2960706d25bceb4d1769; + let test_data_empty_hash = 0x132559f41b7adc7388e0cd52b91fd6837c296b2f9ec1b6d2ed046f7a56db18f8; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index ab4a40540c6..36e5ec115d9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -155,7 +155,8 @@ global FUNCTION_LEAF_PREIMAGE_LENGTH: u64 = 5; global GLOBAL_VARIABLES_LENGTH: u64 = 6 + GAS_FEES_LENGTH; global APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; global L1_TO_L2_MESSAGE_LENGTH: u64 = 6; -global L2_TO_L1_MESSAGE_LENGTH: u64 = 2; +global L2_TO_L1_MESSAGE_LENGTH: u64 = 3; +global SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the value global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 31740a66be7..efb7f6b38c3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -202,7 +202,7 @@ fn compute_l2_l1_hash() { assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2); // Non-zero case - let message = L2ToL1Message { recipient: EthAddress::from_field(3), content: 5 }; + let message = L2ToL1Message { recipient: EthAddress::from_field(3), content: 5, counter: 1234 }; let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), 2, 4, message); assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr index 928239bf935..a64d2629a40 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr @@ -1,9 +1,14 @@ -use crate::{address::EthAddress, constants::L2_TO_L1_MESSAGE_LENGTH, traits::{Deserialize, Empty, Serialize}}; +use crate::{ + address::{AztecAddress, EthAddress}, + constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH}, + traits::{Deserialize, Empty, Serialize}, utils::{arrays::array_concat, reader::Reader} +}; // Note: Not to be confused with L2ToL1Msg in Solidity struct L2ToL1Message { recipient: EthAddress, content: Field, + counter: u32, } impl Empty for L2ToL1Message { @@ -11,19 +16,20 @@ impl Empty for L2ToL1Message { Self { recipient: EthAddress::empty(), content: 0, + counter: 0, } } } impl Eq for L2ToL1Message { fn eq(self, other: Self) -> bool { - (self.recipient == other.recipient) & (self.content == other.content) + (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter) } } impl Serialize for L2ToL1Message { fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] { - [self.recipient.to_field(), self.content] + [self.recipient.to_field(), self.content, self.counter as Field] } } @@ -32,6 +38,52 @@ impl Deserialize for L2ToL1Message { Self { recipient: EthAddress::from_field(values[0]), content: values[1], + counter: values[2] as u32, } } } + +impl L2ToL1Message { + pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message { + ScopedL2ToL1Message { value: self, contract_address } + } +} + +struct ScopedL2ToL1Message { + value: L2ToL1Message, + contract_address: AztecAddress, +} + +impl Eq for ScopedL2ToL1Message { + fn eq(self, other: ScopedL2ToL1Message) -> bool { + (self.value == other.value) + & (self.contract_address == other.contract_address) + } +} + +impl Empty for ScopedL2ToL1Message { + fn empty() -> Self { + ScopedL2ToL1Message { + value: L2ToL1Message::empty(), + contract_address: AztecAddress::empty(), + } + } +} + +impl Serialize for ScopedL2ToL1Message { + fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] { + array_concat(self.value.serialize(), [self.contract_address.to_field()]) + } +} + +impl Deserialize for ScopedL2ToL1Message { + fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self { + let mut reader = Reader::new(values); + let res = Self { + value: reader.read_struct(L2ToL1Message::deserialize), + contract_address: reader.read_struct(AztecAddress::deserialize), + }; + reader.finish(); + res + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 69bf17afcc2..ffe190ebe36 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -12,7 +12,7 @@ use crate::{ read_request::ReadRequestContext, side_effect::SideEffect, validation_requests::{ValidationRequests, ValidationRequestsBuilder} }, - address::AztecAddress, + address::{AztecAddress, EthAddress}, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -21,9 +21,10 @@ use crate::{ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::silo_nullifier, header::Header, mocked::{AggregationObject, Proof, VerificationKey}, - partial_state_reference::PartialStateReference, tests::fixtures, transaction::tx_context::TxContext, - traits::Empty + hash::silo_nullifier, header::Header, + messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, + mocked::{AggregationObject, Proof, VerificationKey}, partial_state_reference::PartialStateReference, + tests::fixtures, transaction::tx_context::TxContext, traits::Empty }; struct FixtureBuilder { @@ -38,7 +39,7 @@ struct FixtureBuilder { // Accumulated data. new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, encrypted_logs_hash: Field, @@ -144,7 +145,7 @@ impl FixtureBuilder { new_nullifiers: self.new_nullifiers.storage.map( |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } ), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -159,7 +160,7 @@ impl FixtureBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -302,6 +303,15 @@ impl FixtureBuilder { } } + pub fn add_l2_to_l1_message(&mut self, content: Field, recipient: EthAddress) { + self.new_l2_to_l1_msgs.push( + ScopedL2ToL1Message { + value: L2ToL1Message { recipient, content, counter: self.next_counter() }, + contract_address: self.storage_contract_address + } + ); + } + pub fn add_public_data_update_request(&mut self, leaf_slot: Field, value: Field) { let update_request = PublicDataUpdateRequest { leaf_slot, new_value: value }; self.public_data_update_requests.push(update_request); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index 4de0a338525..52c277355c8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -75,6 +75,18 @@ pub fn array_cp(array: [T; N]) -> [T; S] where T: Empty { result } +pub fn array_concat(array1: [T; N], array2: [T; M]) -> [T; S] { + assert_eq(N + M, S, "combined array length does not match return array length"); + let mut result = [array1[0]; S]; + for i in 1..N { + result[i] = array1[i]; + } + for i in 0..M { + result[i + N] = array2[i]; + } + result +} + pub fn array_merge(array1: [T; N], array2: [T; N]) -> [T; N] where T: Empty + Eq { let mut result: [T; N] = [T::empty(); N]; let mut i = 0; @@ -195,6 +207,21 @@ fn find_index_not_found() { assert_eq(index, 4); } +#[test] +fn test_array_concat() { + let array0 = [1, 2, 3]; + let array1 = [4, 5]; + let concated = array_concat(array0, array1); + assert_eq(concated, [1, 2, 3, 4, 5]); +} + +#[test(should_fail_with="combined array length does not match return array length")] +fn array_concat_fails_inconsistent_lengths() { + let array0 = [1, 2, 3]; + let array1 = [4, 5]; + let _concated: [Field; 4] = array_concat(array0, array1); +} + #[test] fn check_permutation_basic_test() { let original_array = [1, 2, 3]; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 094991c36b0..8a444f92a4a 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -98,15 +98,17 @@ export const FUNCTION_LEAF_PREIMAGE_LENGTH = 5; export const GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH; export const APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; export const L1_TO_L2_MESSAGE_LENGTH = 6; -export const L2_TO_L1_MESSAGE_LENGTH = 2; +export const L2_TO_L1_MESSAGE_LENGTH = 3; +export const SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; export const MAX_BLOCK_NUMBER_LENGTH = 2; export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; export const READ_REQUEST_LENGTH = 2; export const NOTE_HASH_LENGTH = 2; -export const NOTE_HASH_CONTEXT_LENGTH = 3; +export const NOTE_HASH_CONTEXT_LENGTH = 4; export const NULLIFIER_LENGTH = 3; +export const NULLIFIER_CONTEXT_LENGTH = 4; export const SIDE_EFFECT_LENGTH = 2; export const STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; export const TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index d6602caad31..4536f791000 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -13,6 +13,7 @@ import { MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; +import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; import { NoteHashContext } from '../note_hash.js'; import { NullifierContext } from '../nullifier.js'; import { SideEffect } from '../side_effects.js'; @@ -34,7 +35,7 @@ export class PrivateAccumulatedData { /** * All the new L2 to L1 messages created in this transaction. */ - public newL2ToL1Msgs: Tuple, + public newL2ToL1Msgs: Tuple, /** * Accumulated encrypted logs hash from all the previous kernel iterations. * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. @@ -92,7 +93,7 @@ export class PrivateAccumulatedData { return new PrivateAccumulatedData( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), + reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), Fr.fromBuffer(reader), @@ -115,7 +116,7 @@ export class PrivateAccumulatedData { return new PrivateAccumulatedData( makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext.empty), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), + makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), Fr.zero(), diff --git a/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts b/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts index ef4bb082386..56208b3cbc2 100644 --- a/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts +++ b/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts @@ -1,3 +1,4 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -5,14 +6,14 @@ import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/ import { L2_TO_L1_MESSAGE_LENGTH } from '../constants.gen.js'; export class L2ToL1Message { - constructor(public recipient: EthAddress, public content: Fr) {} + constructor(public recipient: EthAddress, public content: Fr, public counter: number) {} /** * Creates an empty L2ToL1Message with default values. * @returns An instance of L2ToL1Message with empty fields. */ static empty(): L2ToL1Message { - return new L2ToL1Message(EthAddress.ZERO, Fr.zero()); + return new L2ToL1Message(EthAddress.ZERO, Fr.zero(), 0); } /** @@ -21,7 +22,9 @@ export class L2ToL1Message { * @returns True if both recipient and content are equal. */ equals(other: L2ToL1Message): boolean { - return this.recipient.equals(other.recipient) && this.content.equals(other.content); + return ( + this.recipient.equals(other.recipient) && this.content.equals(other.content) && this.counter === other.counter + ); } /** @@ -29,7 +32,7 @@ export class L2ToL1Message { * @returns The buffer. */ toBuffer(): Buffer { - return serializeToBuffer(this.recipient, this.content); + return serializeToBuffer(this.recipient, this.content, this.counter); } /** @@ -37,7 +40,7 @@ export class L2ToL1Message { * @returns An array of fields representing the serialized message. */ toFields(): Fr[] { - const fields = [this.recipient.toField(), this.content]; + const fields = [this.recipient.toField(), this.content, new Fr(this.counter)]; if (fields.length !== L2_TO_L1_MESSAGE_LENGTH) { throw new Error( `Invalid number of fields for L2ToL1Message. Expected ${L2_TO_L1_MESSAGE_LENGTH}, got ${fields.length}`, @@ -53,7 +56,7 @@ export class L2ToL1Message { */ static fromFields(fields: Fr[] | FieldReader): L2ToL1Message { const reader = FieldReader.asReader(fields); - return new L2ToL1Message(reader.readObject(EthAddress), reader.readField()); + return new L2ToL1Message(reader.readObject(EthAddress), reader.readField(), reader.readU32()); } /** @@ -63,7 +66,7 @@ export class L2ToL1Message { */ static fromBuffer(buffer: Buffer | BufferReader): L2ToL1Message { const reader = BufferReader.asReader(buffer); - return new L2ToL1Message(reader.readObject(EthAddress), reader.readObject(Fr)); + return new L2ToL1Message(reader.readObject(EthAddress), reader.readObject(Fr), reader.readNumber()); } /** @@ -71,6 +74,31 @@ export class L2ToL1Message { * @returns True if both recipient and content are zero. */ isEmpty(): boolean { - return this.recipient.isZero() && this.content.isZero(); + return this.recipient.isZero() && this.content.isZero() && !this.counter; + } +} + +export class ScopedL2ToL1Message { + constructor(public value: L2ToL1Message, public contractAddress: AztecAddress) {} + + static empty() { + return new ScopedL2ToL1Message(L2ToL1Message.empty(), AztecAddress.ZERO); + } + + equals(other: ScopedL2ToL1Message): boolean { + return this.value.equals(other.value) && this.contractAddress.equals(other.contractAddress); + } + + toBuffer(): Buffer { + return serializeToBuffer(this.value, this.contractAddress); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new ScopedL2ToL1Message(reader.readObject(L2ToL1Message), reader.readObject(AztecAddress)); + } + + isEmpty(): boolean { + return this.value.isEmpty() && this.contractAddress.isZero(); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 3401439d0f6..18ed66ed818 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -54,7 +54,6 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_HINTS, @@ -75,9 +74,7 @@ import { NUM_BASE_PARITY_PER_ROOT_PARITY, NUM_MSGS_PER_BASE_PARITY, NoteHash, - NoteHashContext, Nullifier, - NullifierContext, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, NullifierLeafPreimage, @@ -91,12 +88,9 @@ import { PartialStateReference, Point, PreviousRollupData, - PrivateAccumulatedData, PrivateCallData, PrivateCallStackItem, PrivateCircuitPublicInputs, - PrivateKernelCircuitPublicInputs, - PrivateKernelData, PrivateKernelTailCircuitPublicInputs, Proof, PublicAccumulatedData, @@ -161,18 +155,10 @@ function makeNoteHash(seed: number) { return new NoteHash(fr(seed), seed + 1); } -function makeNoteHashContext(seed: number) { - return new NoteHashContext(fr(seed), seed + 1, seed + 2, makeAztecAddress(seed + 3)); -} - function makeNullifier(seed: number) { return new Nullifier(fr(seed), seed + 1, fr(seed + 2)); } -function makeNullifierContext(seed: number) { - return new NullifierContext(fr(seed), seed + 1, fr(seed + 2), makeAztecAddress(seed + 3)); -} - /** * Creates an arbitrary tx context with the given seed. * @param seed - The seed to use for generating the tx context. @@ -362,27 +348,6 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul ); } -/** - * Creates arbitrary accumulated data. - * @param seed - The seed to use for generating the accumulated data. - * @returns An accumulated data. - */ -export function makePrivateAccumulatedData(seed = 1, full = false) { - const tupleGenerator = full ? makeTuple : makeHalfFullTuple; - - return new PrivateAccumulatedData( - tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHashContext, seed + 0x120, NoteHashContext.empty), - tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, makeNullifierContext, seed + 0x200, NullifierContext.empty), - tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), - tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x700, SideEffect.empty), // encrypted logs hashes - tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x800, SideEffect.empty), // unencrypted logs hashes - fr(seed + 0x900), // encrypted_log_preimages_length - fr(seed + 0xa00), // unencrypted_log_preimages_length - tupleGenerator(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x400, CallRequest.empty), - tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x500, CallRequest.empty), - ); -} - /** * Creates arbitrary aggregation object. * @param seed - The seed to use for generating the aggregation object. @@ -478,21 +443,6 @@ export function makePublicKernelCircuitPublicInputs( ); } -/** - * Creates arbitrary private kernel inner circuit public inputs. - * @param seed - The seed to use for generating the kernel circuit public inputs. - * @returns Private kernel circuit public inputs. - */ -export function makePrivateKernelCircuitPublicInputs(seed = 1, full = true): PrivateKernelCircuitPublicInputs { - return new PrivateKernelCircuitPublicInputs( - makeAggregationObject(seed), - fr(seed + 0x100), - makeValidationRequests(seed), - makePrivateAccumulatedData(seed, full), - makeConstantData(seed + 0x100), - ); -} - /** * Creates arbitrary private kernel tail circuit public inputs. * @param seed - The seed to use for generating the kernel circuit public inputs. @@ -644,22 +594,6 @@ export function makeRollupKernelData(seed = 1, kernelPublicInputs?: KernelCircui ); } -/** - * Makes arbitrary previous kernel data. - * @param seed - The seed to use for generating the previous kernel data. - * @param inputs - The kernel public inputs to use for generating the private kernel inner data. - * @returns A previous kernel data. - */ -export function makePrivateKernelInnerData(seed = 1, inputs?: PrivateKernelCircuitPublicInputs): PrivateKernelData { - return new PrivateKernelData( - inputs ?? makePrivateKernelCircuitPublicInputs(seed, true), - new Proof(Buffer.alloc(16, seed + 0x80)), - makeVerificationKey(), - 0x42, - makeTuple(VK_TREE_HEIGHT, fr, 0x1000), - ); -} - /** * Makes arbitrary proof. * @param seed - The seed to use for generating/mocking the proof. @@ -1108,7 +1042,7 @@ export function makeL2ToL1Message(seed = 0): L2ToL1Message { const recipient = EthAddress.fromField(new Fr(seed)); const content = new Fr(seed + 1); - return new L2ToL1Message(recipient, content); + return new L2ToL1Message(recipient, content, seed + 2); } /** 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 d27388e3237..9222d95fb05 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -29,7 +29,7 @@ import { Header, KernelCircuitPublicInputs, type KernelData, - type L2ToL1Message, + L2ToL1Message, type LeafDataReadHint, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, @@ -108,6 +108,7 @@ import { type RootParityInputs, type RootRollupInputs, RootRollupPublicInputs, + ScopedL2ToL1Message, type SettledReadHint, SideEffect, type StateDiffHints, @@ -157,6 +158,7 @@ import { type ReadRequestContext as ReadRequestContextNoir, type ReadRequest as ReadRequestNoir, type RollupValidationRequests as RollupValidationRequestsNoir, + type ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, type SideEffect as SideEffectNoir, type TxContext as TxContextNoir, type TxRequest as TxRequestNoir, @@ -744,9 +746,25 @@ export function mapL2ToL1MessageToNoir(message: L2ToL1Message): L2ToL1MessageNoi return { recipient: mapEthAddressToNoir(message.recipient), content: mapFieldToNoir(message.content), + counter: mapNumberToNoir(message.counter), }; } +function mapL2ToL1MessageFromNoir(message: L2ToL1MessageNoir) { + return new L2ToL1Message( + mapEthAddressFromNoir(message.recipient), + mapFieldFromNoir(message.content), + mapNumberFromNoir(message.counter), + ); +} + +function mapScopedL2ToL1MessageFromNoir(message: ScopedL2ToL1MessageNoir) { + return new ScopedL2ToL1Message( + mapL2ToL1MessageFromNoir(message.value), + mapAztecAddressFromNoir(message.contract_address), + ); +} + /** * Maps private circuit public inputs to noir private circuit public inputs. * @param privateCircuitPublicInputs - The private circuit public inputs. @@ -1071,7 +1089,11 @@ export function mapPrivateAccumulatedDataFromNoir( return new PrivateAccumulatedData( mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapNoteHashContextFromNoir), mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierContextFromNoir), - mapTupleFromNoir(privateAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), + mapTupleFromNoir( + privateAccumulatedData.new_l2_to_l1_msgs, + MAX_NEW_L2_TO_L1_MSGS_PER_TX, + mapScopedL2ToL1MessageFromNoir, + ), mapTupleFromNoir(privateAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir( privateAccumulatedData.unencrypted_logs_hashes, diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index 8a42f1e6796..ea08c9a6387 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -153,7 +153,7 @@ describe('journal', () => { journal.writeL1Message(recipient, msgHash); const journalUpdates = journal.flush(); - expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: msgHash }]); + expect(journalUpdates.newL1Messages).toEqual([expect.objectContaining({ recipient, content: msgHash })]); }); }); @@ -260,8 +260,8 @@ describe('journal', () => { ), ]); expect(journalUpdates.newL1Messages).toEqual([ - { recipient, content: commitment }, - { recipient, content: commitmentT1 }, + expect.objectContaining({ recipient, content: commitment }), + expect.objectContaining({ recipient, content: commitmentT1 }), ]); expect(journalUpdates.nullifierChecks).toEqual([ expect.objectContaining({ nullifier: commitment, exists: true }), @@ -403,7 +403,7 @@ describe('journal', () => { Buffer.concat(log.data.map(f => f.toBuffer())), ), ]); - expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: commitment }]); + expect(journalUpdates.newL1Messages).toEqual([expect.objectContaining({ recipient, content: commitment })]); }); it('Can fork and merge journals', () => { diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 5c21dd175a3..5330f67e916 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -189,7 +189,7 @@ export class AvmPersistableStateManager { public writeL1Message(recipient: EthAddress | Fr, content: Fr) { this.log.debug(`L1Messages(${recipient}) += ${content}.`); const recipientAddress = recipient instanceof EthAddress ? recipient : EthAddress.fromField(recipient); - this.newL1Messages.push(new L2ToL1Message(recipientAddress, content)); + this.newL1Messages.push(new L2ToL1Message(recipientAddress, content, 0)); } public writeLog(contractAddress: Fr, event: Fr, log: Fr[]) { diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts index 88c7cadd138..376f64a8cd9 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -465,7 +465,9 @@ describe('Accrued Substate', () => { ).execute(context); const journalState = context.persistableState.flush(); - expect(journalState.newL1Messages).toEqual([{ recipient: EthAddress.fromField(recipient), content }]); + expect(journalState.newL1Messages).toEqual([ + expect.objectContaining({ recipient: EthAddress.fromField(recipient), content }), + ]); }); }); diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 14995aa727a..158fdf601c4 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -8,7 +8,6 @@ import { GlobalVariables, type Header, L1_TO_L2_MSG_TREE_HEIGHT, - L2ToL1Message, NULLIFIER_TREE_HEIGHT, NullifierLeaf, NullifierLeafPreimage, @@ -400,10 +399,8 @@ describe('ACIR public execution simulator', () => { // Assert the l2 to l1 message was created expect(result.newL2ToL1Messages.length).toEqual(1); - - const expectedNewMessage = new L2ToL1Message(portalContractAddress, pedersenHash(params)); - - expect(result.newL2ToL1Messages[0]).toEqual(expectedNewMessage); + expect(result.newL2ToL1Messages[0].recipient).toEqual(portalContractAddress); + expect(result.newL2ToL1Messages[0].content).toEqual(pedersenHash(params)); }); it('Should be able to create a nullifier from the public context', async () => { diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 2bbd079ad89..87ebffb4638 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -9,7 +9,6 @@ import { type GasSettings, type GlobalVariables, type Header, - L2ToL1Message, NoteHash, Nullifier, ReadRequest, @@ -147,7 +146,7 @@ export async function convertAvmResults( const unencryptedLogsHashes = newWorldState.newLogsHashes.map( logHash => new SideEffect(logHash.logHash, logHash.counter), ); - const newL2ToL1Messages = newWorldState.newL1Messages.map(m => new L2ToL1Message(m.recipient, m.content)); + const newL2ToL1Messages = newWorldState.newL1Messages; const returnValues = result.output; From 478ce6686de35b624a63a86a1f38ee20e8af7a4a Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Sat, 4 May 2024 10:54:43 +0000 Subject: [PATCH 04/13] Update snapshots. --- .../__snapshots__/private_call_stack_item.test.ts.snap | 4 ++-- .../private_circuit_public_inputs.test.ts.snap | 4 ++-- .../__snapshots__/public_call_stack_item.test.ts.snap | 8 ++++---- .../public_circuit_public_inputs.test.ts.snap | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 0a6b285dc0c..42eaa1ea400 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x17fd6ffcb3394b845069dc87e055c37ac50599f274130fac69c6fe919bfe382e>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x0700e78957e211c160928fab8448fc9b738b08ce880412e433eb4bcf3c1093c7>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x07e0e054d39be2aab72d74cc72ef8adc61016744fd985c6736e14e710d14c875>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x2ee678bb0265d628d54121367fde6609d72fd13045bf7bf71bf5939c96a151c2>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 72ffed28cf3..080e428ec4d 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x29129c06414f4ac73bf889692c7011f91727d4cdbfe4fe143e6adee69b565cc8>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x1c397d7bced95ebd2725a5c33ed11c065ef84ab72a98d085453fe7c3d7af9b28>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0ab17c0893be4023ff61f8c2df5a0106c1709f7b10c2fadd53581da7a7d799d6>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0217b1e3ea41780afd1e17a886d9b03ead3f8f9167c473d5676291647cdbc305>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 4a2e6a33179..0ccb386246e 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1122a7d7e6174b7e5d111c8eb0233564d3a1ffd755afc7ce4b594d738e2770d7"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0f7624c0d5ea65fcec318c4d34cb3fcbf9c67435aebbf1548b3c90ef641424f8"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1595b195f0faa3a492109039dc807b291d0edd81a5e3a380866d5098ffd505dd"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1177a69fbc37f0ebdf290025414ff72504497840f174896bd427d0f30ec21c55"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x302550c2014c51737798139c9a80af984fa23be608c9758de295181944dddf66>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x020b98dcc882881a349edfd43044d58c8703fdcfc9d4b250b799d951608dcd6b>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1682642d96f9873ed85f245b4ca2ec93d2a0e11ba8e3d614f94ba409030af2c9>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x18d2b726728360b534121bb15accd1059f7df38225e76768e64d3e3040122440>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index 6cf756de088..834668caf75 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x1a2da219bb2e3ac24519fd844365c4f656fc3ba8c58f2960706d25bceb4d1769>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x132559f41b7adc7388e0cd52b91fd6837c296b2f9ec1b6d2ed046f7a56db18f8>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x05db8cb4a08d8d1f5b0f38b2ef50f0bf70b4ed33099f649062326084197f1b79>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0ac3cb8eb6605fc7aa83e9420eb988c1f6c9a5dcc2457c133216624bc6932619>`; From 451383ba9d09b4aff46b2b1803e4156318cbc8c7 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Sat, 4 May 2024 12:09:22 +0000 Subject: [PATCH 05/13] Fix type conversion. --- .../noir-protocol-circuits-types/src/type_conversion.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 73661608644..54d4518a63c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -765,6 +765,13 @@ function mapScopedL2ToL1MessageFromNoir(message: ScopedL2ToL1MessageNoir) { ); } +function mapScopedL2ToL1MessageToNoir(message: ScopedL2ToL1Message): ScopedL2ToL1MessageNoir { + return { + value: mapL2ToL1MessageToNoir(message.value), + contract_address: mapAztecAddressToNoir(message.contractAddress), + }; +} + /** * Maps private circuit public inputs to noir private circuit public inputs. * @param privateCircuitPublicInputs - The private circuit public inputs. @@ -1120,7 +1127,7 @@ export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): P return { new_note_hashes: mapTuple(data.newNoteHashes, mapNoteHashContextToNoir), new_nullifiers: mapTuple(data.newNullifiers, mapNullifierContextToNoir), - new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapFieldToNoir), + new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapScopedL2ToL1MessageToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapSideEffectToNoir), encrypted_log_preimages_length: mapFieldToNoir(data.encryptedLogPreimagesLength), From f418f9fa2e267a29993bc01b5f568d723624b281 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Sat, 4 May 2024 16:42:11 +0000 Subject: [PATCH 06/13] Fix. --- .../accumulated_data/combined_accumulated_data.nr | 5 ++++- yarn-project/aztec-node/src/aztec-node/server.ts | 12 +++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index e6907de06f4..1a49b8de968 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -48,7 +48,10 @@ impl CombinedAccumulatedData { CombinedAccumulatedData { new_note_hashes: array_merge(non_revertible.new_note_hashes, revertible.new_note_hashes).map(|n: NoteHash| n.value), new_nullifiers: array_merge(non_revertible.new_nullifiers, revertible.new_nullifiers).map(|n: Nullifier| n.value), - new_l2_to_l1_msgs: revertible.new_l2_to_l1_msgs, + new_l2_to_l1_msgs: array_merge( + non_revertible.new_l2_to_l1_msgs, + revertible.new_l2_to_l1_msgs + ), encrypted_logs_hash, unencrypted_logs_hash, encrypted_log_preimages_length: non_revertible.encrypted_log_preimages_length diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 343130a1b38..ac37b1ee0d3 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -32,8 +32,6 @@ import { type Header, INITIAL_L2_BLOCK_NUM, type L1_TO_L2_MSG_TREE_HEIGHT, - L2_TO_L1_MESSAGE_LENGTH, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, type NOTE_HASH_TREE_HEIGHT, type NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, @@ -44,7 +42,6 @@ import { import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; @@ -453,11 +450,7 @@ export class AztecNodeService implements AztecNode { throw new Error('Block is not defined'); } - // We multiply the number of messages per block by the length of each message because each message occupies - // 2 leaves in the tree! - const l2ToL1Messages = block.body.txEffects.flatMap(txEffect => - padArrayEnd(txEffect.l2ToL1Msgs, Fr.ZERO, MAX_NEW_L2_TO_L1_MSGS_PER_TX * L2_TO_L1_MESSAGE_LENGTH), - ); + const l2ToL1Messages = block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); const indexOfL2ToL1Message = BigInt( l2ToL1Messages.findIndex(l2ToL1MessageInBlock => l2ToL1MessageInBlock.equals(l2ToL1Message)), @@ -467,7 +460,8 @@ export class AztecNodeService implements AztecNode { throw new Error('The L2ToL1Message you are trying to prove inclusion of does not exist'); } - const treeHeight = Math.ceil(Math.log2(l2ToL1Messages.length)); + // Match how l2ToL1TreeHeight is calculated in Rollup.sol. + const treeHeight = block.header.contentCommitment.txTreeHeight.toNumber() + 1; // The root of this tree is the out_hash calculated in Noir => we truncate to match Noir's SHA const tree = new StandardTree( openTmpStore(true), From 9e1398669d7c2b5446657468dceb8c967d01597c Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 7 May 2024 22:13:51 +0000 Subject: [PATCH 07/13] Rename NoteHashContext to ScopedNoteHash. --- .../kernel_circuit_public_inputs_composer.nr | 17 ++--- ...e_kernel_circuit_public_inputs_composer.nr | 2 +- .../src/private_kernel_tail.nr | 20 ++--- .../src/private_kernel_tail_to_public.nr | 20 ++--- .../src/public_kernel_app_logic.nr | 4 +- .../src/note_hash_read_request_reset.nr | 10 +-- .../private_validation_request_processor.nr | 4 +- .../src/reset/transient_data.nr | 40 +++++----- .../src/tests/squash_transient_data.nr | 6 +- .../private_accumulated_data.nr | 4 +- .../private_accumulated_data_builder.nr | 23 +++--- .../crates/types/src/abis/note_hash.nr | 75 +++++++++++-------- .../crates/types/src/constants.nr | 4 +- .../crates/types/src/tests/fixture_builder.nr | 17 ++--- .../crates/types/src/utils/reader.nr | 4 + ...build_note_hash_read_request_hints.test.ts | 7 +- .../build_note_hash_read_request_hints.ts | 8 +- .../hints/build_transient_data_hints.test.ts | 10 +-- .../src/hints/build_transient_data_hints.ts | 4 +- .../kernel/private_accumulated_data.ts | 8 +- ...vate_kernel_tail_circuit_private_inputs.ts | 10 +-- .../circuits.js/src/structs/note_hash.ts | 43 +++++------ .../src/type_conversion.ts | 24 +++--- .../src/kernel_prover/kernel_prover.test.ts | 8 +- .../build_private_kernel_tail_outputs.ts | 6 +- 25 files changed, 191 insertions(+), 187 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 8a3a6717e01..890d1037405 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -3,8 +3,7 @@ use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, PublicKernelCircuitPublicInputs}, - note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::{SideEffect, Ordered}, - gas::Gas + note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::{SideEffect, Ordered}, gas::Gas }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, @@ -28,12 +27,12 @@ struct KernelCircuitPublicInputsComposer { public_inputs: PrivateKernelCircuitPublicInputsBuilder, previous_kernel: PrivateKernelData, // Final data - note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], // Hints 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], - sorted_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], @@ -46,11 +45,11 @@ struct KernelCircuitPublicInputsComposer { impl KernelCircuitPublicInputsComposer { pub fn new( previous_kernel: PrivateKernelData, - note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], 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], - sorted_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], @@ -137,11 +136,11 @@ impl KernelCircuitPublicInputsComposer { let note_hashes = self.public_inputs.end.new_note_hashes.storage; for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { let note_hash = note_hashes[i]; - if note_hash.value != 0 { - let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); + if note_hash.value() != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); let nonce = compute_note_hash_nonce(first_nullifier.value, i); let unique_note_hash = compute_unique_siloed_note_hash(nonce, siloed); - self.public_inputs.end.new_note_hashes.storage[i].value = unique_note_hash; + self.public_inputs.end.new_note_hashes.storage[i].note_hash.value = unique_note_hash; } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index b1c1860b66a..a0f14106266 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -153,7 +153,7 @@ impl PrivateKernelCircuitPublicInputsComposer { assert( (nullifier_counter == 0) | (nullifier_counter > note_hash.counter), "Invalid nullifier counter" ); - self.public_inputs.end.new_note_hashes.push(note_hash.to_context(nullifier_counter, source.storage_contract_address)); + self.public_inputs.end.new_note_hashes.push(note_hash.scope(nullifier_counter, source.storage_contract_address)); } } } 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 debab44f900..81110bf8c4b 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect + note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -14,7 +14,7 @@ use dep::types::{ // Can just be KernelCircuitPublicInputs. struct PrivateKernelTailOutputs { - note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], } @@ -24,7 +24,7 @@ struct PrivateKernelTailHints { note_hash_read_request_hints: NoteHashReadRequestHints, nullifier_read_request_hints: NullifierReadRequestHints, master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], - sorted_new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], @@ -97,7 +97,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, side_effect::SideEffect, gas::Gas + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, side_effect::SideEffect, gas::Gas }, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, sha256_to_field, silo_note_hash, silo_nullifier}, @@ -134,14 +134,14 @@ mod tests { // note_hashes for the given note_hashes. pub fn compute_output_note_hashes( self, - note_hashes: [NoteHashContext; N] + note_hashes: [ScopedNoteHash; N] ) -> [Field; N] { let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0); let mut unique_siloed_note_hashes = [0; N]; for i in 0..N { let note_hash = note_hashes[i]; - if note_hash.value != 0 { - let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); + if note_hash.value() != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); let nonce = compute_note_hash_nonce(first_nullifier.value, i); unique_siloed_note_hashes[i] = compute_unique_siloed_note_hash(nonce, siloed); } @@ -177,7 +177,7 @@ mod tests { pub fn nullify_pending_note_hash(&mut self, nullifier_index: u64, note_hash_index: u64) { self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter; - self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).value; + self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash.value; self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; } @@ -185,7 +185,7 @@ mod tests { pub fn execute(&mut self) -> KernelCircuitPublicInputs { let sorted = sort_get_sorted_hints( self.previous_kernel.new_note_hashes.storage, - |a: NoteHashContext, b: NoteHashContext| a.counter < b.counter + |a: ScopedNoteHash, b: ScopedNoteHash| a.counter() < b.counter() ); let sorted_new_note_hashes = sorted.sorted_array; let sorted_new_note_hashes_indexes = sorted.sorted_index_hints; @@ -495,7 +495,7 @@ mod tests { let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; - let mut reversed_note_hashes = [NoteHashContext::empty(); 10]; + let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; let mut reversed_nullifiers = [NullifierContext::empty(); 10]; for i in 0..10 { 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 f2199651053..410fdb4c99b 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::NoteHashContext, nullifier::NullifierContext, side_effect::SideEffect + note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -14,7 +14,7 @@ use dep::types::{ // Can just be PublicKernelCircuitPublicInputs. struct PrivateKernelTailToPublicOutputs { - note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], } @@ -24,7 +24,7 @@ struct PrivateKernelTailToPublicHints { note_hash_read_request_hints: NoteHashReadRequestHints, nullifier_read_request_hints: NullifierReadRequestHints, master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], - sorted_new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], @@ -99,7 +99,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, - note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, side_effect::SideEffect }, grumpkin_private_key::GrumpkinPrivateKey, @@ -135,13 +135,13 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. - pub fn compute_output_note_hashes(self, note_hashes: [NoteHashContext; N]) -> [NoteHash; N] { + pub fn compute_output_note_hashes(self, note_hashes: [ScopedNoteHash; N]) -> [NoteHash; N] { let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0); let mut unique_siloed_note_hashes = [NoteHash::empty(); N]; for i in 0..N { let note_hash = note_hashes[i]; - if note_hash.value != 0 { - let siloed = silo_note_hash(note_hash.contract_address, note_hash.value); + if note_hash.value() != 0 { + let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); let nonce = compute_note_hash_nonce(first_nullifier.value, i); unique_siloed_note_hashes[i] = NoteHash { value: compute_unique_siloed_note_hash(nonce, siloed), @@ -183,7 +183,7 @@ mod tests { pub fn nullify_pending_note_hash(&mut self, nullifier_index: u64, note_hash_index: u64) { self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter; - self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).value; + self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).value(); self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; } @@ -191,7 +191,7 @@ mod tests { pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { let sorted = sort_get_sorted_hints( self.previous_kernel.new_note_hashes.storage, - |a: NoteHashContext, b: NoteHashContext| a.counter < b.counter + |a: ScopedNoteHash, b: ScopedNoteHash| a.counter() < b.counter() ); let sorted_new_note_hashes = sorted.sorted_array; let sorted_new_note_hashes_indexes = sorted.sorted_index_hints; @@ -407,7 +407,7 @@ mod tests { let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; - let mut reversed_note_hashes = [NoteHashContext::empty(); 10]; + let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; let mut reversed_nullifiers = [NullifierContext::empty(); 10]; for i in 0..10 { diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 0e68e7a73ef..c561384f859 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -78,7 +78,7 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest }, @@ -187,7 +187,7 @@ mod tests { let contract_address = builder.public_call.contract_address; // Setup 2 new note hashes on the previous kernel. builder.previous_kernel.append_new_note_hashes(2); - let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: NoteHashContext| NoteHash { value: n.value, counter: n.counter }); + let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash); // Setup 2 new note hashes on the current public inputs. let current = [ NoteHash { value: previous[1].value + 1, counter: 3 }, 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 310a455da19..688c83ea927 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 @@ -48,7 +48,7 @@ mod tests { use dep::types::{ address::AztecAddress, abis::{ - membership_witness::NoteHashMembershipWitness, note_hash::NoteHashContext, + membership_witness::NoteHashMembershipWitness, note_hash::NoteHash, note_hash_leaf_preimage::NoteHashLeafPreimage, read_request::ReadRequestContext }, constants::NOTE_HASH_TREE_HEIGHT, hash::silo_note_hash, @@ -72,8 +72,8 @@ mod tests { ]; global pending_values = [ - NoteHashContext { value: inner_note_hashes[2], counter: 2, nullifier_counter: 0, contract_address }, - NoteHashContext { value: inner_note_hashes[3], counter: 8, nullifier_counter: 0, contract_address }, + NoteHash { value: inner_note_hashes[2], counter: 2, }.scope(0, contract_address), + NoteHash { value: inner_note_hashes[3], counter: 8, }.scope(0, contract_address), ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, @@ -161,7 +161,7 @@ mod tests { fn test_reset_note_hash_read_requests_wrong_hinted_value() { let mut tainted_pending_values = pending_values; // Tweak the value to be something different. - tainted_pending_values[0].value += 1; + tainted_pending_values[0].note_hash.value += 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( @@ -180,7 +180,7 @@ mod tests { let pending_read = read_requests[hint.read_request_index]; let mut tainted_pending_values = pending_values; // Tweak the counter of the value to be greater than the read request. - tainted_pending_values[hint.pending_value_index].counter = pending_read.counter + 1; + tainted_pending_values[hint.pending_value_index].note_hash.counter = pending_read.counter + 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( 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 199f5655db9..0d277770e05 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 @@ -3,7 +3,7 @@ use crate::{ nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests }; use dep::types::{ - abis::{note_hash::NoteHashContext, nullifier::NullifierContext, validation_requests::ValidationRequests}, + abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext, validation_requests::ValidationRequests}, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M @@ -14,7 +14,7 @@ use dep::types::{ struct PrivateValidationRequestProcessor { validation_requests: ValidationRequests, note_hash_read_request_hints: NoteHashReadRequestHints, - pending_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + pending_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, nullifier_read_request_hints: NullifierReadRequestHints, pending_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index 7287b9ed624..d487f8f4b83 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -1,9 +1,9 @@ -use dep::types::{abis::{note_hash::NoteHashContext, nullifier::NullifierContext}, traits::is_empty}; +use dep::types::{abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext}, traits::is_empty}; pub fn verify_squashed_transient_note_hashes_and_nullifiers( - note_hashes: [NoteHashContext; NUM_NOTE_HASHES], + note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [NullifierContext; NUM_NULLIFIERS], - expected_note_hashes: [NoteHashContext; NUM_NOTE_HASHES], + expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS] @@ -19,7 +19,7 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers note_hash.counter); + // assert(nullifier.counter > note_hash.counter()); note_hashes_removed += 1; @@ -67,14 +67,14 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers { num_note_hashes: u64, num_nullifiers: u64, - note_hashes: [NoteHashContext; NUM_NOTE_HASHES], + note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [NullifierContext; NUM_NULLIFIERS], - expected_note_hashes: [NoteHashContext; NUM_NOTE_HASHES], + expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS], @@ -85,9 +85,9 @@ mod tests { let contract_address = AztecAddress::from_field(987654); let note_hashes = [ - NoteHashContext { value: 11, counter: 100, nullifier_counter: 500, contract_address }, - NoteHashContext { value: 22, counter: 200, nullifier_counter: 0, contract_address }, - NoteHashContext { value: 33, counter: 300, nullifier_counter: 400, contract_address } + NoteHash { value: 11, counter: 100 }.scope(500, contract_address), + NoteHash { value: 22, counter: 200 }.scope(0, contract_address), + NoteHash { value: 33, counter: 300 }.scope(400, contract_address) ]; let nullifiers = [ @@ -96,7 +96,7 @@ mod tests { NullifierContext { value: 66, counter: 600, note_hash: 0, contract_address } ]; - let expected_note_hashes = [note_hashes[1], NoteHashContext::empty(), NoteHashContext::empty()]; + let expected_note_hashes = [note_hashes[1], ScopedNoteHash::empty(), ScopedNoteHash::empty()]; let expected_nullifiers = [nullifiers[2], NullifierContext::empty(), NullifierContext::empty()]; let transient_nullifier_indexes_for_note_hashes = [1, 3, 0]; @@ -118,9 +118,9 @@ mod tests { let contract_address = AztecAddress::from_field(987654); let note_hashes = [ - NoteHashContext { value: 11, counter: 100, nullifier_counter: 500, contract_address }, - NoteHashContext { value: 22, counter: 200, nullifier_counter: 600, contract_address }, - NoteHashContext { value: 33, counter: 300, nullifier_counter: 400, contract_address } + NoteHash { value: 11, counter: 100 }.scope(500, contract_address), + NoteHash { value: 22, counter: 200 }.scope(600, contract_address), + NoteHash { value: 33, counter: 300 }.scope(400, contract_address) ]; let nullifiers = [ @@ -129,7 +129,7 @@ mod tests { NullifierContext { value: 66, counter: 600, note_hash: 22, contract_address } ]; - let expected_note_hashes = [NoteHashContext::empty(); 3]; + let expected_note_hashes = [ScopedNoteHash::empty(); 3]; let expected_nullifiers = [NullifierContext::empty(); 3]; let transient_nullifier_indexes_for_note_hashes = [1, 2, 0]; @@ -188,7 +188,7 @@ mod tests { fn mismatch_note_hash_value() { let mut builder = TestDataBuilder::default_all_clear(); - builder.note_hashes[1].value += 1; + builder.note_hashes[1].note_hash.value += 1; builder.verify(); } @@ -215,7 +215,7 @@ mod tests { fn unexpected_note_hash_value() { let mut builder = TestDataBuilder::default_all_clear(); - builder.expected_note_hashes[2].value = 11; + builder.expected_note_hashes[2].note_hash.value = 11; builder.verify(); } @@ -224,7 +224,7 @@ mod tests { fn wrong_expected_note_hash_value() { let mut builder = TestDataBuilder::default(); - builder.expected_note_hashes[0].value += 1; + builder.expected_note_hashes[0].note_hash.value += 1; builder.verify(); } @@ -233,7 +233,7 @@ mod tests { fn wrong_expected_note_hash_counter() { let mut builder = TestDataBuilder::default(); - builder.expected_note_hashes[0].counter += 1; + builder.expected_note_hashes[0].note_hash.counter += 1; builder.verify(); } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr index 409ed06d5b9..2e24360b272 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr @@ -1,7 +1,7 @@ -use dep::types::abis::{note_hash::NoteHashContext, nullifier::NullifierContext}; +use dep::types::abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext}; -pub fn squash_transient_note_hashes(note_hashes: [NoteHashContext; N]) -> [NoteHashContext; N] { - let mut final_note_hashes = [NoteHashContext::empty(); N]; +pub fn squash_transient_note_hashes(note_hashes: [ScopedNoteHash; N]) -> [ScopedNoteHash; N] { + let mut final_note_hashes = [ScopedNoteHash::empty(); N]; let mut num_note_hashes = 0; for i in 0..N { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 14d53d9437b..d6f21ff8326 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - call_request::CallRequest, gas::Gas, note_hash::NoteHashContext, nullifier::NullifierContext, + call_request::CallRequest, gas::Gas, note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::SideEffect }, messaging::l2_to_l1_message::ScopedL2ToL1Message @@ -12,7 +12,7 @@ use crate::constants::{ }; struct PrivateAccumulatedData { - new_note_hashes: [NoteHashContext; MAX_NEW_NOTE_HASHES_PER_TX], + new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 037cf8c06d1..6a004bf7115 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -7,7 +7,7 @@ use crate::{ private_accumulated_data::PrivateAccumulatedData, public_accumulated_data::PublicAccumulatedData, public_accumulated_data_builder::PublicAccumulatedDataBuilder }, - call_request::CallRequest, note_hash::{NoteHash, NoteHashContext}, nullifier::NullifierContext, + call_request::CallRequest, note_hash::{NoteHash, ScopedNoteHash}, nullifier::NullifierContext, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, constants::{ @@ -24,7 +24,7 @@ use crate::{ // .to_combined: KernelCircuitPublicInputs.end // .split_to_public: PublicKernelCircuitPublicInputs.(end,end_non_revertible) struct PrivateAccumulatedDataBuilder { - new_note_hashes: BoundedVec, + new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, @@ -63,7 +63,7 @@ impl PrivateAccumulatedDataBuilder { let gas_used = self.to_metered_gas_used() + Gas::tx_overhead() + teardown_gas; CombinedAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), + new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), encrypted_logs_hash, @@ -124,7 +124,7 @@ impl PrivateAccumulatedDataBuilder { for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { let note_hash = self.new_note_hashes.storage[i]; let public_note_hash = note_hash.expose_to_public(); - if note_hash.counter < min_revertible_side_effect_counter { + if note_hash.counter() < min_revertible_side_effect_counter { non_revertible_builder.new_note_hashes.push(public_note_hash); if !is_empty(public_note_hash) { non_revertible_da_gas_used += DA_GAS_PER_FIELD ; @@ -206,9 +206,9 @@ mod tests { use crate::{ abis::{ accumulated_data::private_accumulated_data_builder::PrivateAccumulatedDataBuilder, gas::Gas, - call_request::CallRequest, caller_context::CallerContext, - note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, - public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect + call_request::CallRequest, caller_context::CallerContext, note_hash::NoteHash, + nullifier::{Nullifier, NullifierContext}, public_data_update_request::PublicDataUpdateRequest, + side_effect::SideEffect }, address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} @@ -217,14 +217,15 @@ mod tests { #[test] unconstrained fn splits_revertible_and_non_revertible() { let mut builder = PrivateAccumulatedDataBuilder::empty(); + let contract_address = AztecAddress::from_field(8989); let min_revertible_side_effect_counter = 7; // Non revertible: counter < 7 let non_revertible_note_hashes = [ - NoteHashContext { value: 1, counter: 1, nullifier_counter: 20, contract_address: AztecAddress::from_field(7788) }, - NoteHashContext { value: 2, counter: 3, nullifier_counter: 5, contract_address: AztecAddress::from_field(5566) } + NoteHash { value: 1, counter: 1 }.scope(20, contract_address), + NoteHash { value: 2, counter: 3 }.scope(5, contract_address) ]; let non_revertible_nullifiers = [ @@ -256,8 +257,8 @@ mod tests { // Revertible: counter >= 7 let revertible_note_hashes = [ - NoteHashContext { value: 3, counter: 7, nullifier_counter: 15, contract_address: AztecAddress::from_field(9900) }, - NoteHashContext { value: 4, counter: 10, nullifier_counter: 0, contract_address: AztecAddress::from_field(7788) } + NoteHash { value: 3, counter: 7 }.scope(15, contract_address), + NoteHash { value: 4, counter: 10 }.scope(0, contract_address) ]; let revertible_nullifiers = [ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index 595a5447529..f32d9398d94 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -1,7 +1,8 @@ use crate::{ abis::read_request::ReadRequestContext, address::AztecAddress, - abis::side_effect::{Ordered, Readable}, constants::{NOTE_HASH_LENGTH, NOTE_HASH_CONTEXT_LENGTH}, - traits::{Empty, Serialize, Deserialize} + abis::side_effect::{Ordered, OrderedValue, Readable}, + constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize}, + utils::{arrays::array_concat, reader::Reader} }; use dep::std::cmp::Eq; @@ -42,67 +43,75 @@ impl Deserialize for NoteHash { } impl NoteHash { - pub fn to_context(self, nullifier_counter: u32, contract_address: AztecAddress) -> NoteHashContext { - NoteHashContext { value: self.value, counter: self.counter, nullifier_counter, contract_address } + pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash { + ScopedNoteHash { note_hash: self, nullifier_counter, contract_address } } } -struct NoteHashContext { - value: Field, - counter: u32, +struct ScopedNoteHash { + note_hash: NoteHash, nullifier_counter: u32, contract_address: AztecAddress, } -impl Ordered for NoteHashContext { +impl Ordered for ScopedNoteHash { fn counter(self) -> u32 { - self.counter + self.note_hash.counter } } -impl Eq for NoteHashContext { - fn eq(self, other: NoteHashContext) -> bool { - (self.value == other.value) - & (self.counter == other.counter) +impl OrderedValue for ScopedNoteHash { + fn value(self) -> Field { + self.note_hash.value + } + fn counter(self) -> u32 { + self.note_hash.counter + } +} + +impl Eq for ScopedNoteHash { + fn eq(self, other: ScopedNoteHash) -> bool { + (self.note_hash == other.note_hash) & (self.nullifier_counter == other.nullifier_counter) & (self.contract_address == other.contract_address) } } -impl Empty for NoteHashContext { +impl Empty for ScopedNoteHash { fn empty() -> Self { - NoteHashContext { - value: 0, - counter: 0, + ScopedNoteHash { + note_hash: NoteHash::empty(), nullifier_counter: 0, contract_address: AztecAddress::zero(), } } } -impl Serialize for NoteHashContext { - fn serialize(self) -> [Field; NOTE_HASH_CONTEXT_LENGTH] { - [self.value, self.counter as Field, self.nullifier_counter as Field, self.contract_address.to_field()] +impl Serialize for ScopedNoteHash { + fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] { + array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()]) } } -impl Deserialize for NoteHashContext { - fn deserialize(values: [Field; NOTE_HASH_CONTEXT_LENGTH]) -> Self { - Self { - value: values[0], - counter: values[1] as u32, - nullifier_counter: values[2] as u32, - contract_address: AztecAddress::from_field(values[3]), - } +impl Deserialize for ScopedNoteHash { + fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self { + let mut reader = Reader::new(values); + let res = Self { + note_hash: reader.read_struct(NoteHash::deserialize), + nullifier_counter: reader.read_u32(), + contract_address: reader.read_struct(AztecAddress::deserialize), + }; + reader.finish(); + res } } -impl Readable for NoteHashContext { +impl Readable for ScopedNoteHash { fn assert_match_read_request(self, read_request: ReadRequestContext) { - assert_eq(self.value, read_request.value, "Value of the note hash does not match read request"); + assert_eq(self.note_hash.value, read_request.value, "Value of the note hash does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the note hash does not match read request"); assert( - read_request.counter > self.counter, "Read request counter must be greater than the counter of the note hash" + read_request.counter > self.note_hash.counter, "Read request counter must be greater than the counter of the note hash" ); assert( (self.nullifier_counter == 0) | (read_request.counter < self.nullifier_counter), "Read request counter must be less than the nullifier counter of the note hash" @@ -110,9 +119,9 @@ impl Readable for NoteHashContext { } } -impl NoteHashContext { +impl ScopedNoteHash { pub fn expose_to_public(self) -> NoteHash { // Hide the actual counter when exposing it to the public kernel. - NoteHash { value: self.value, counter: 0 } + NoteHash { value: self.note_hash.value, counter: 0 } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index ad1a8d4a09d..c3f5f796bf3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -156,14 +156,14 @@ global GLOBAL_VARIABLES_LENGTH: u64 = 6 + GAS_FEES_LENGTH; global APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; global L1_TO_L2_MESSAGE_LENGTH: u64 = 6; global L2_TO_L1_MESSAGE_LENGTH: u64 = 3; -global SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; +global SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the value global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; global READ_REQUEST_LENGTH = 2; global NOTE_HASH_LENGTH = 2; -global NOTE_HASH_CONTEXT_LENGTH = 4; +global SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; global NULLIFIER_LENGTH = 3; global NULLIFIER_CONTEXT_LENGTH = 4; global SIDE_EFFECT_LENGTH = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index d12af6a0d8c..6e368328cf0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -6,7 +6,7 @@ use crate::{ global_variables::GlobalVariables, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, kernel_data::{PrivateKernelData, PublicKernelData, KernelData}, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, NoteHashContext}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::SideEffect, @@ -38,7 +38,7 @@ struct FixtureBuilder { public_teardown_call_request: CallRequest, // Accumulated data. - new_note_hashes: BoundedVec, + new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -143,7 +143,7 @@ impl FixtureBuilder { pub fn to_public_accumulated_data(self) -> PublicAccumulatedData { PublicAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| NoteHash { value: n.value, counter: n.counter }), + new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), new_nullifiers: self.new_nullifiers.storage.map( |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } ), @@ -160,7 +160,7 @@ impl FixtureBuilder { pub fn to_combined_accumulated_data(self) -> CombinedAccumulatedData { CombinedAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: NoteHashContext| n.value), + new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), encrypted_logs_hash: self.encrypted_logs_hash, @@ -256,14 +256,7 @@ impl FixtureBuilder { } pub fn add_new_note_hash(&mut self, value: Field) { - self.new_note_hashes.push( - NoteHashContext { - value, - counter: self.next_counter(), - nullifier_counter: 0, - contract_address: self.storage_contract_address - } - ); + self.new_note_hashes.push(NoteHash { value, counter: self.next_counter() }.scope(0, self.storage_contract_address)); } pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u64) { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr index dffc118e7d8..4f1b5ab95a1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr @@ -14,6 +14,10 @@ impl Reader { result } + pub fn read_u32(&mut self) -> u32 { + self.read() as u32 + } + pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] { for i in 0..K { result[i] = self.data[self.offset + i]; 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 86248eb1b9c..1aa3b1f0880 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 @@ -6,12 +6,13 @@ import { type Tuple } from '@aztec/foundation/serialize'; import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { siloNoteHash } from '../hash/index.js'; import { - NoteHashContext, + NoteHash, type NoteHashReadRequestHints, NoteHashReadRequestHintsBuilder, PendingReadHint, ReadRequestContext, ReadRequestStatus, + type ScopedNoteHash, SettledReadHint, } from '../structs/index.js'; import { buildNoteHashReadRequestHints } from './build_note_hash_read_request_hints.js'; @@ -26,7 +27,7 @@ describe('buildNoteHashReadRequestHints', () => { settledLeafIndexes.includes(leafIndex) ? ({} as any) : undefined, }; let noteHashReadRequests: Tuple; - let noteHashes: Tuple; + let noteHashes: Tuple; let noteHashLeafIndexMap: Map = new Map(); let expectedHints: NoteHashReadRequestHints; let numReadRequests = 0; @@ -38,7 +39,7 @@ describe('buildNoteHashReadRequestHints', () => { const makeReadRequest = (value: number, counter = 2) => new ReadRequestContext(new Fr(value), counter, contractAddress); - const makeNoteHash = (value: number, counter = 1) => new NoteHashContext(new Fr(value), counter, 0, contractAddress); + const makeNoteHash = (value: number, counter = 1) => new NoteHash(new Fr(value), counter).scope(0, contractAddress); const readPendingNoteHash = ({ noteHashIndex, 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 45ea0ea3b98..2e21c66d978 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 @@ -7,13 +7,13 @@ import { } from '../constants.gen.js'; import { type MembershipWitness, - type NoteHashContext, NoteHashReadRequestHintsBuilder, type ReadRequestContext, + type ScopedNoteHash, } from '../structs/index.js'; import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; -function isValidNoteHashReadRequest(readRequest: ReadRequestContext, noteHash: NoteHashContext) { +function isValidNoteHashReadRequest(readRequest: ReadRequestContext, noteHash: ScopedNoteHash) { return ( noteHash.contractAddress.equals(readRequest.contractAddress) && readRequest.counter > noteHash.counter && @@ -26,14 +26,14 @@ export async function buildNoteHashReadRequestHints( getNoteHashMembershipWitness(leafIndex: bigint): Promise>; }, noteHashReadRequests: Tuple, - noteHashes: Tuple, + noteHashes: Tuple, noteHashLeafIndexMap: Map, ) { const builder = new NoteHashReadRequestHintsBuilder(); const numReadRequests = countAccumulatedItems(noteHashReadRequests); - const noteHashMap: Map = new Map(); + const noteHashMap: Map = new Map(); getNonEmptyItems(noteHashes).forEach((noteHash, index) => { const value = noteHash.value.toBigInt(); const arr = noteHashMap.get(value) ?? []; diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index 27f183ead6e..dc92fb636aa 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -1,18 +1,18 @@ -import { AztecAddress, Fr, NoteHashContext, NullifierContext } from '@aztec/circuits.js'; +import { AztecAddress, Fr, NoteHash, NullifierContext, type ScopedNoteHash } from '@aztec/circuits.js'; import { buildTransientDataHints } from './build_transient_data_hints.js'; describe('buildTransientDataHints', () => { const contractAddress = AztecAddress.fromBigInt(987654n); - let noteHashes: NoteHashContext[]; + let noteHashes: ScopedNoteHash[]; let nullifiers: NullifierContext[]; beforeEach(() => { noteHashes = [ - new NoteHashContext(new Fr(11), 100, 700, contractAddress), - new NoteHashContext(new Fr(22), 200, 0, contractAddress), - new NoteHashContext(new Fr(33), 300, 500, contractAddress), + new NoteHash(new Fr(11), 100).scope(700, contractAddress), + new NoteHash(new Fr(22), 200).scope(0, contractAddress), + new NoteHash(new Fr(33), 300).scope(500, contractAddress), ]; nullifiers = [ new NullifierContext(new Fr(44), 400, new Fr(0), contractAddress), diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts index 2ef02973192..adb277f6979 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts @@ -1,9 +1,9 @@ -import { type NoteHashContext, type NullifierContext, countAccumulatedItems } from '@aztec/circuits.js'; +import { type NullifierContext, type ScopedNoteHash, countAccumulatedItems } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildTransientDataHints( - noteHashes: Tuple, + noteHashes: Tuple, nullifiers: Tuple, noteHashesLength: NOTE_HASHES_LEN = noteHashes.length as NOTE_HASHES_LEN, nullifiersLength: NULLIFIERS_LEN = nullifiers.length as NULLIFIERS_LEN, diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index 4536f791000..ed02f8d5a33 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -14,7 +14,7 @@ import { } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; -import { NoteHashContext } from '../note_hash.js'; +import { ScopedNoteHash } from '../note_hash.js'; import { NullifierContext } from '../nullifier.js'; import { SideEffect } from '../side_effects.js'; @@ -27,7 +27,7 @@ export class PrivateAccumulatedData { /** * The new note hashes made in this transaction. */ - public newNoteHashes: Tuple, + public newNoteHashes: Tuple, /** * The new nullifiers made in this transaction. */ @@ -91,7 +91,7 @@ export class PrivateAccumulatedData { static fromBuffer(buffer: Buffer | BufferReader): PrivateAccumulatedData { const reader = BufferReader.asReader(buffer); return new PrivateAccumulatedData( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), + reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), @@ -114,7 +114,7 @@ export class PrivateAccumulatedData { static empty() { return new PrivateAccumulatedData( - makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext.empty), + makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index e9d6155a44d..9df24b12970 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -10,7 +10,7 @@ import { } from '../../constants.gen.js'; import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; -import { NoteHashContext } from '../note_hash.js'; +import { ScopedNoteHash } from '../note_hash.js'; import { NullifierContext } from '../nullifier.js'; import { type NoteHashReadRequestHints, @@ -23,7 +23,7 @@ import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelTailOutputs { constructor( - public noteHashes: Tuple, + public noteHashes: Tuple, public nullifiers: Tuple, ) {} @@ -34,7 +34,7 @@ export class PrivateKernelTailOutputs { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new PrivateKernelTailOutputs( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), + reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), ); } @@ -66,7 +66,7 @@ export class PrivateKernelTailHints { /* * The sorted new note hashes. */ - public sortedNewNoteHashes: Tuple, + public sortedNewNoteHashes: Tuple, /** * The sorted new note hashes indexes. Maps original to sorted. */ @@ -128,7 +128,7 @@ export class PrivateKernelTailHints { reader.readObject({ fromBuffer: noteHashReadRequestHintsFromBuffer }), reader.readObject({ fromBuffer: nullifierReadRequestHintsFromBuffer }), reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext), + reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), diff --git a/yarn-project/circuits.js/src/structs/note_hash.ts b/yarn-project/circuits.js/src/structs/note_hash.ts index ac4f9acee20..824b788e275 100644 --- a/yarn-project/circuits.js/src/structs/note_hash.ts +++ b/yarn-project/circuits.js/src/structs/note_hash.ts @@ -36,53 +36,54 @@ export class NoteHash { toString(): string { return `value=${this.value} counter=${this.counter}`; } + + scope(nullifierCounter: number, contractAddress: AztecAddress) { + return new ScopedNoteHash(this, nullifierCounter, contractAddress); + } } -export class NoteHashContext implements Ordered { - constructor( - public value: Fr, - public counter: number, - public nullifierCounter: number, - public contractAddress: AztecAddress, - ) {} +export class ScopedNoteHash implements Ordered { + constructor(public noteHash: NoteHash, public nullifierCounter: number, public contractAddress: AztecAddress) {} + + get counter() { + return this.noteHash.counter; + } + + get value() { + return this.noteHash.value; + } toFields(): Fr[] { - return [this.value, new Fr(this.counter), new Fr(this.nullifierCounter), this.contractAddress.toField()]; + return [...this.noteHash.toFields(), new Fr(this.nullifierCounter), this.contractAddress.toField()]; } static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new NoteHashContext( - reader.readField(), - reader.readU32(), + return new ScopedNoteHash( + reader.readObject(NoteHash), reader.readU32(), AztecAddress.fromField(reader.readField()), ); } isEmpty() { - return this.value.isZero() && !this.counter && !this.nullifierCounter && this.contractAddress.isZero(); + return this.noteHash.isEmpty() && !this.nullifierCounter && this.contractAddress.isZero(); } static empty() { - return new NoteHashContext(Fr.zero(), 0, 0, AztecAddress.ZERO); + return new ScopedNoteHash(NoteHash.empty(), 0, AztecAddress.ZERO); } toBuffer(): Buffer { - return serializeToBuffer(this.value, this.counter, this.nullifierCounter, this.contractAddress); + return serializeToBuffer(this.noteHash, this.nullifierCounter, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new NoteHashContext( - Fr.fromBuffer(reader), - reader.readNumber(), - reader.readNumber(), - AztecAddress.fromBuffer(reader), - ); + return new ScopedNoteHash(NoteHash.fromBuffer(reader), reader.readNumber(), AztecAddress.fromBuffer(reader)); } toString(): string { - return `value=${this.value} counter=${this.counter} nullifierCounter=${this.nullifierCounter} contractAddress=${this.contractAddress}`; + return `noteHash=${this.noteHash} nullifierCounter=${this.nullifierCounter} contractAddress=${this.contractAddress}`; } } 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 54d4518a63c..8804ca012c9 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -53,7 +53,6 @@ import { NUM_BYTES_PER_SHA256, type NonMembershipHint, NoteHash, - NoteHashContext, type NoteHashReadRequestHints, Nullifier, NullifierContext, @@ -109,6 +108,7 @@ import { type RootRollupInputs, RootRollupPublicInputs, ScopedL2ToL1Message, + ScopedNoteHash, type SettledReadHint, SideEffect, type StateDiffHints, @@ -142,7 +142,6 @@ import { type EthAddress as NoirEthAddress, type Field as NoirField, type GrumpkinPoint as NoirPoint, - type NoteHashContext as NoteHashContextNoir, type NoteHash as NoteHashNoir, type NullifierContext as NullifierContextNoir, type NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, @@ -159,6 +158,7 @@ import { type ReadRequest as ReadRequestNoir, type RollupValidationRequests as RollupValidationRequestsNoir, type ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, + type ScopedNoteHash as ScopedNoteHashNoir, type SideEffect as SideEffectNoir, type TxContext as TxContextNoir, type TxRequest as TxRequestNoir, @@ -559,19 +559,17 @@ function mapNoteHashFromNoir(noteHash: NoteHashNoir) { return new NoteHash(mapFieldFromNoir(noteHash.value), mapNumberFromNoir(noteHash.counter)); } -function mapNoteHashContextToNoir(noteHash: NoteHashContext): NoteHashContextNoir { +function mapScopedNoteHashToNoir(noteHash: ScopedNoteHash): ScopedNoteHashNoir { return { - value: mapFieldToNoir(noteHash.value), - counter: mapNumberToNoir(noteHash.counter), + note_hash: mapNoteHashToNoir(noteHash.noteHash), nullifier_counter: mapNumberToNoir(noteHash.nullifierCounter), contract_address: mapAztecAddressToNoir(noteHash.contractAddress), }; } -function mapNoteHashContextFromNoir(noteHash: NoteHashContextNoir) { - return new NoteHashContext( - mapFieldFromNoir(noteHash.value), - mapNumberFromNoir(noteHash.counter), +function mapScopedNoteHashFromNoir(noteHash: ScopedNoteHashNoir) { + return new ScopedNoteHash( + mapNoteHashFromNoir(noteHash.note_hash), mapNumberFromNoir(noteHash.nullifier_counter), mapAztecAddressFromNoir(noteHash.contract_address), ); @@ -1095,7 +1093,7 @@ export function mapPrivateAccumulatedDataFromNoir( privateAccumulatedData: PrivateAccumulatedDataNoir, ): PrivateAccumulatedData { return new PrivateAccumulatedData( - mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapNoteHashContextFromNoir), + mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapScopedNoteHashFromNoir), mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierContextFromNoir), mapTupleFromNoir( privateAccumulatedData.new_l2_to_l1_msgs, @@ -1125,7 +1123,7 @@ export function mapPrivateAccumulatedDataFromNoir( export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): PrivateAccumulatedDataNoir { return { - new_note_hashes: mapTuple(data.newNoteHashes, mapNoteHashContextToNoir), + new_note_hashes: mapTuple(data.newNoteHashes, mapScopedNoteHashToNoir), new_nullifiers: mapTuple(data.newNullifiers, mapNullifierContextToNoir), new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapScopedL2ToL1MessageToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), @@ -1463,7 +1461,7 @@ export function mapPrivateKernelInnerCircuitPrivateInputsToNoir( function mapPrivateKernelTailOutputsToNoir(inputs: PrivateKernelTailOutputs): PrivateKernelTailOutputsNoir { return { - note_hashes: mapTuple(inputs.noteHashes, mapNoteHashContextToNoir), + note_hashes: mapTuple(inputs.noteHashes, mapScopedNoteHashToNoir), nullifiers: mapTuple(inputs.nullifiers, mapNullifierContextToNoir), }; } @@ -1478,7 +1476,7 @@ function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): Privat note_hash_read_request_hints: mapNoteHashReadRequestHintsToNoir(inputs.noteHashReadRequestHints), nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), - sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapNoteHashContextToNoir), + sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapScopedNoteHashToNoir), sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapNullifierContextToNoir), sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index 257a5458643..58f29d4ceda 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -6,11 +6,11 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MembershipWitness, NoteHash, - NoteHashContext, PrivateCallStackItem, PrivateCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PrivateKernelTailCircuitPublicInputs, + ScopedNoteHash, type TxRequest, VK_TREE_HEIGHT, VerificationKey, @@ -80,11 +80,9 @@ describe('Kernel Prover', () => { const createProofOutput = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelCircuitPublicInputs.empty(); - const noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHashContext.empty); + const noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty); for (let i = 0; i < newNoteIndices.length; i++) { - noteHashes[i] = new NoteHashContext( - generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]), - 0, + noteHashes[i] = new NoteHash(generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]), 0).scope( 0, contractAddress, ); diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts index 7ced5fa6fb6..5e46e4162a0 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts @@ -1,22 +1,22 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, - NoteHashContext, NullifierContext, PrivateKernelTailOutputs, + ScopedNoteHash, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelTailOutputs( - prevNoteHashes: Tuple, + prevNoteHashes: Tuple, prevNullifiers: Tuple, ) { // Propagate note hashes that are not linked to a nullifier. // Note that note hashes can't link to the first nullifier (counter == 0). const noteHashes = padArrayEnd( prevNoteHashes.filter(n => !n.nullifierCounter), - NoteHashContext.empty(), + ScopedNoteHash.empty(), MAX_NEW_NOTE_HASHES_PER_TX, ); From 3ee9e248be2bc300a8ea09716b28efe4740369bc Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 7 May 2024 22:27:30 +0000 Subject: [PATCH 08/13] Rename. --- .../kernel_circuit_public_inputs_composer.nr | 4 ++-- .../private_accumulated_data_builder.nr | 8 ++++---- .../types/src/messaging/l2_to_l1_message.nr | 20 ++++++++++++------- .../crates/types/src/tests/fixture_builder.nr | 9 +++------ .../src/structs/l2_to_l1_message.ts | 8 ++++---- .../src/type_conversion.ts | 4 ++-- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 890d1037405..2505dd6823e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -166,9 +166,9 @@ impl KernelCircuitPublicInputsComposer { msg.contract_address, tx_context.version, tx_context.chain_id, - msg.value + msg.message ); - self.public_inputs.end.new_l2_to_l1_msgs.storage[i].value.content = siloed; + self.public_inputs.end.new_l2_to_l1_msgs.storage[i].message.content = siloed; } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 6a004bf7115..1a4e0d95118 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -65,7 +65,7 @@ impl PrivateAccumulatedDataBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hash, unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -155,10 +155,10 @@ impl PrivateAccumulatedDataBuilder { for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { let msg = self.new_l2_to_l1_msgs.storage[i]; - if msg.value.counter < min_revertible_side_effect_counter { - non_revertible_builder.new_l2_to_l1_msgs.push(msg.value.content); + if msg.counter() < min_revertible_side_effect_counter { + non_revertible_builder.new_l2_to_l1_msgs.push(msg.message.content); } else { - revertible_builder.new_l2_to_l1_msgs.push(msg.value.content); + revertible_builder.new_l2_to_l1_msgs.push(msg.message.content); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr index a64d2629a40..8f21f8e2c77 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr @@ -1,6 +1,6 @@ use crate::{ address::{AztecAddress, EthAddress}, - constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH}, + constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH}, abis::side_effect::Ordered, traits::{Deserialize, Empty, Serialize}, utils::{arrays::array_concat, reader::Reader} }; @@ -45,18 +45,24 @@ impl Deserialize for L2ToL1Message { impl L2ToL1Message { pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message { - ScopedL2ToL1Message { value: self, contract_address } + ScopedL2ToL1Message { message: self, contract_address } } } struct ScopedL2ToL1Message { - value: L2ToL1Message, + message: L2ToL1Message, contract_address: AztecAddress, } +impl Ordered for ScopedL2ToL1Message { + fn counter(self) -> u32 { + self.message.counter + } +} + impl Eq for ScopedL2ToL1Message { fn eq(self, other: ScopedL2ToL1Message) -> bool { - (self.value == other.value) + (self.message == other.message) & (self.contract_address == other.contract_address) } } @@ -64,7 +70,7 @@ impl Eq for ScopedL2ToL1Message { impl Empty for ScopedL2ToL1Message { fn empty() -> Self { ScopedL2ToL1Message { - value: L2ToL1Message::empty(), + message: L2ToL1Message::empty(), contract_address: AztecAddress::empty(), } } @@ -72,7 +78,7 @@ impl Empty for ScopedL2ToL1Message { impl Serialize for ScopedL2ToL1Message { fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] { - array_concat(self.value.serialize(), [self.contract_address.to_field()]) + array_concat(self.message.serialize(), [self.contract_address.to_field()]) } } @@ -80,7 +86,7 @@ impl Deserialize for ScopedL2ToL1Message { fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self { let mut reader = Reader::new(values); let res = Self { - value: reader.read_struct(L2ToL1Message::deserialize), + message: reader.read_struct(L2ToL1Message::deserialize), contract_address: reader.read_struct(AztecAddress::deserialize), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 6e368328cf0..4c283cc8f94 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -147,7 +147,7 @@ impl FixtureBuilder { new_nullifiers: self.new_nullifiers.storage.map( |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } ), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -162,7 +162,7 @@ impl FixtureBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.value.content), + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -302,10 +302,7 @@ impl FixtureBuilder { pub fn add_l2_to_l1_message(&mut self, content: Field, recipient: EthAddress) { self.new_l2_to_l1_msgs.push( - ScopedL2ToL1Message { - value: L2ToL1Message { recipient, content, counter: self.next_counter() }, - contract_address: self.storage_contract_address - } + L2ToL1Message { recipient, content, counter: self.next_counter() }.scope(self.storage_contract_address) ); } diff --git a/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts b/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts index 56208b3cbc2..8d5a1e214d4 100644 --- a/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts +++ b/yarn-project/circuits.js/src/structs/l2_to_l1_message.ts @@ -79,18 +79,18 @@ export class L2ToL1Message { } export class ScopedL2ToL1Message { - constructor(public value: L2ToL1Message, public contractAddress: AztecAddress) {} + constructor(public message: L2ToL1Message, public contractAddress: AztecAddress) {} static empty() { return new ScopedL2ToL1Message(L2ToL1Message.empty(), AztecAddress.ZERO); } equals(other: ScopedL2ToL1Message): boolean { - return this.value.equals(other.value) && this.contractAddress.equals(other.contractAddress); + return this.message.equals(other.message) && this.contractAddress.equals(other.contractAddress); } toBuffer(): Buffer { - return serializeToBuffer(this.value, this.contractAddress); + return serializeToBuffer(this.message, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { @@ -99,6 +99,6 @@ export class ScopedL2ToL1Message { } isEmpty(): boolean { - return this.value.isEmpty() && this.contractAddress.isZero(); + return this.message.isEmpty() && this.contractAddress.isZero(); } } 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 8804ca012c9..816301c724c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -758,14 +758,14 @@ function mapL2ToL1MessageFromNoir(message: L2ToL1MessageNoir) { function mapScopedL2ToL1MessageFromNoir(message: ScopedL2ToL1MessageNoir) { return new ScopedL2ToL1Message( - mapL2ToL1MessageFromNoir(message.value), + mapL2ToL1MessageFromNoir(message.message), mapAztecAddressFromNoir(message.contract_address), ); } function mapScopedL2ToL1MessageToNoir(message: ScopedL2ToL1Message): ScopedL2ToL1MessageNoir { return { - value: mapL2ToL1MessageToNoir(message.value), + message: mapL2ToL1MessageToNoir(message.message), contract_address: mapAztecAddressToNoir(message.contractAddress), }; } From 7b7853377826a68af7b0840f688e8b04b62b7043 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 7 May 2024 23:12:21 +0000 Subject: [PATCH 09/13] Rename NullifierContext to ScopedNullifier. --- .../crates/private-kernel-lib/src/common.nr | 4 +- .../kernel_circuit_public_inputs_composer.nr | 24 +++--- ...e_kernel_circuit_public_inputs_composer.nr | 8 +- .../src/private_kernel_init.nr | 2 +- .../src/private_kernel_tail.nr | 26 +++---- .../src/private_kernel_tail_to_public.nr | 28 +++---- .../src/public_kernel_app_logic.nr | 6 +- .../src/public_kernel_tail.nr | 21 ++--- .../src/nullifier_read_request_reset.nr | 13 ++-- .../private_validation_request_processor.nr | 4 +- .../src/reset/transient_data.nr | 41 +++++----- .../src/tests/squash_transient_data.nr | 8 +- .../private_accumulated_data.nr | 4 +- .../private_accumulated_data_builder.nr | 18 ++--- .../crates/types/src/abis/nullifier.nr | 77 +++++++++---------- .../crates/types/src/constants.nr | 2 +- .../crates/types/src/tests/fixture_builder.nr | 12 ++- ...build_nullifier_read_request_hints.test.ts | 7 +- .../build_nullifier_read_request_hints.ts | 16 ++-- .../hints/build_transient_data_hints.test.ts | 14 ++-- .../src/hints/build_transient_data_hints.ts | 6 +- .../kernel/private_accumulated_data.ts | 8 +- ...vate_kernel_tail_circuit_private_inputs.ts | 10 +-- .../circuits.js/src/structs/nullifier.ts | 44 ++++++----- .../src/type_conversion.ts | 26 +++---- .../build_private_kernel_tail_hints.ts | 4 +- .../build_private_kernel_tail_outputs.ts | 8 +- 27 files changed, 215 insertions(+), 226 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr index 618741fd50b..940e0230db2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr @@ -142,7 +142,9 @@ fn contract_logic(private_call: PrivateCallData) { } pub fn validate_previous_kernel_values(end: PrivateAccumulatedData) { - assert(end.new_nullifiers[0].value != 0, "The 0th nullifier in the accumulated nullifier array is zero"); + assert( + end.new_nullifiers[0].value() != 0, "The 0th nullifier in the accumulated nullifier array is zero" + ); } pub fn validate_call_against_request(private_call: PrivateCallData, request: CallRequest) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 2505dd6823e..5abc9c8f4f4 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -3,7 +3,7 @@ use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, PublicKernelCircuitPublicInputs}, - note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::{SideEffect, Ordered}, gas::Gas + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::{SideEffect, Ordered}, gas::Gas }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, @@ -28,13 +28,13 @@ struct KernelCircuitPublicInputsComposer { previous_kernel: PrivateKernelData, // Final data note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], // Hints 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], sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -46,12 +46,12 @@ impl KernelCircuitPublicInputsComposer { pub fn new( previous_kernel: PrivateKernelData, note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], 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], sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -130,15 +130,15 @@ impl KernelCircuitPublicInputsComposer { } fn silo_note_hashes(&mut self) { - let first_nullifier = self.public_inputs.end.new_nullifiers.get_unchecked(0); - assert(first_nullifier.value != 0, "The 0th nullifier in the accumulated nullifier array is zero"); + let first_nullifier = self.public_inputs.end.new_nullifiers.get_unchecked(0).value(); + assert(first_nullifier != 0, "The 0th nullifier in the accumulated nullifier array is zero"); let note_hashes = self.public_inputs.end.new_note_hashes.storage; for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { let note_hash = note_hashes[i]; if note_hash.value() != 0 { let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); - let nonce = compute_note_hash_nonce(first_nullifier.value, i); + let nonce = compute_note_hash_nonce(first_nullifier, i); let unique_note_hash = compute_unique_siloed_note_hash(nonce, siloed); self.public_inputs.end.new_note_hashes.storage[i].note_hash.value = unique_note_hash; } @@ -149,9 +149,9 @@ impl KernelCircuitPublicInputsComposer { let nullifiers = self.public_inputs.end.new_nullifiers.storage; for i in 1..MAX_NEW_NOTE_HASHES_PER_TX { // i starts from 1 to skip the first nullifier. let nullifier = nullifiers[i]; - if nullifier.value != 0 { - let siloed = silo_nullifier(nullifier.contract_address, nullifier.value); - self.public_inputs.end.new_nullifiers.storage[i].value = siloed; + if nullifier.value() != 0 { + let siloed = silo_nullifier(nullifier.contract_address, nullifier.value()); + self.public_inputs.end.new_nullifiers.storage[i].nullifier.value = siloed; } } } @@ -242,7 +242,7 @@ impl KernelCircuitPublicInputsComposer { assert(self.note_hashes[i].nullifier_counter == 0, "Unresolved transient note hash"); } for i in 0..self.nullifiers.len() { - assert(self.nullifiers[i].note_hash == 0, "Unresolved transient nullifier"); + assert(self.nullifiers[i].nullified_note_hash() == 0, "Unresolved transient nullifier"); } self.public_inputs.end.new_note_hashes = array_to_bounded_vec(self.note_hashes); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index a0f14106266..45f859e54e7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -2,7 +2,7 @@ use dep::types::{ abis::{ call_request::CallRequest, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder}, - max_block_number::MaxBlockNumber, nullifier::NullifierContext, + max_block_number::MaxBlockNumber, nullifier::Nullifier, private_circuit_public_inputs::PrivateCircuitPublicInputs }, address::AztecAddress, @@ -37,9 +37,7 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.min_revertible_side_effect_counter = private_call_public_inputs.min_revertible_side_effect_counter; // Since it's the first iteration, we need to push the the tx hash nullifier into the `new_nullifiers` array - public_inputs.end.new_nullifiers.push( - NullifierContext { value: tx_request.hash(), note_hash: 0, counter: 0, contract_address: AztecAddress::zero() } - ); + public_inputs.end.new_nullifiers.push(Nullifier { value: tx_request.hash(), note_hash: 0, counter: 0 }.scope(AztecAddress::zero())); // Note that we do not need to nullify the transaction request nonce anymore. // Should an account want to additionally use nonces for replay protection or handling cancellations, // they will be able to do so in the account contract logic: @@ -163,7 +161,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..nullifiers.len() { let nullifier = nullifiers[i]; if nullifier.value != 0 { - self.public_inputs.end.new_nullifiers.push(nullifier.to_context(source.storage_contract_address)); + self.public_inputs.end.new_nullifiers.push(nullifier.scope(source.storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index a795d4578b7..fd12d41c650 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -150,7 +150,7 @@ mod tests { // Check the first nullifier is hash of the signed tx request let tx_hash = builder.tx_request.hash(); - assert_eq(public_inputs.end.new_nullifiers[0].value, tx_hash); + assert_eq(public_inputs.end.new_nullifiers[0].value(), tx_hash); // Log preimages length should increase by `(un)encrypted_log_preimages_length` from private input assert_eq( 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 81110bf8c4b..48be18e3dee 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::SideEffect + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -15,7 +15,7 @@ use dep::types::{ // Can just be KernelCircuitPublicInputs. struct PrivateKernelTailOutputs { note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], } struct PrivateKernelTailHints { @@ -26,7 +26,7 @@ struct PrivateKernelTailHints { master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -97,7 +97,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, side_effect::SideEffect, gas::Gas + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, side_effect::SideEffect, gas::Gas }, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, sha256_to_field, silo_note_hash, silo_nullifier}, @@ -142,18 +142,18 @@ mod tests { let note_hash = note_hashes[i]; if note_hash.value() != 0 { let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); - let nonce = compute_note_hash_nonce(first_nullifier.value, i); + let nonce = compute_note_hash_nonce(first_nullifier.value(), i); unique_siloed_note_hashes[i] = compute_unique_siloed_note_hash(nonce, siloed); } } unique_siloed_note_hashes } - pub fn compute_output_nullifiers(_self: Self, nullifiers: [NullifierContext; N]) -> [Field; N] { + pub fn compute_output_nullifiers(_self: Self, nullifiers: [ScopedNullifier; N]) -> [Field; N] { let mut output = [0; N]; - output[0] = nullifiers[0].value; + output[0] = nullifiers[0].value(); for i in 1..N { - output[i] = silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value); + output[i] = silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value()); } output } @@ -176,8 +176,8 @@ mod tests { } pub fn nullify_pending_note_hash(&mut self, nullifier_index: u64, note_hash_index: u64) { - self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter; - self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash.value; + self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter(); + self.previous_kernel.new_nullifiers.storage[nullifier_index].nullifier.note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash.value; self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; } @@ -192,7 +192,7 @@ mod tests { let sorted = sort_get_sorted_hints( self.previous_kernel.new_nullifiers.storage, - |a: NullifierContext, b: NullifierContext| a.counter < b.counter + |a: ScopedNullifier, b: ScopedNullifier| a.counter() < b.counter() ); let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; @@ -388,7 +388,7 @@ mod tests { builder.add_pending_nullifier_read_request(1); let nullifier_being_read = builder.previous_kernel.new_nullifiers.storage[2]; let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter - 1; + read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); @@ -496,7 +496,7 @@ mod tests { let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; - let mut reversed_nullifiers = [NullifierContext::empty(); 10]; + let mut reversed_nullifiers = [ScopedNullifier::empty(); 10]; for i in 0..10 { reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); 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 410fdb4c99b..d56e45296ff 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 @@ -3,7 +3,7 @@ use dep::reset_kernel_lib::{NoteHashReadRequestHints, NullifierReadRequestHints, use dep::types::{ abis::{ kernel_data::PrivateKernelData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::ScopedNoteHash, nullifier::NullifierContext, side_effect::SideEffect + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::SideEffect }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -15,7 +15,7 @@ use dep::types::{ // Can just be PublicKernelCircuitPublicInputs. struct PrivateKernelTailToPublicOutputs { note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], } struct PrivateKernelTailToPublicHints { @@ -26,7 +26,7 @@ struct PrivateKernelTailToPublicHints { master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], @@ -99,7 +99,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, side_effect::SideEffect }, grumpkin_private_key::GrumpkinPrivateKey, @@ -136,13 +136,13 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. pub fn compute_output_note_hashes(self, note_hashes: [ScopedNoteHash; N]) -> [NoteHash; N] { - let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0); + let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0).value(); let mut unique_siloed_note_hashes = [NoteHash::empty(); N]; for i in 0..N { let note_hash = note_hashes[i]; if note_hash.value() != 0 { let siloed = silo_note_hash(note_hash.contract_address, note_hash.value()); - let nonce = compute_note_hash_nonce(first_nullifier.value, i); + let nonce = compute_note_hash_nonce(first_nullifier, i); unique_siloed_note_hashes[i] = NoteHash { value: compute_unique_siloed_note_hash(nonce, siloed), counter: 0, // Counter is cleared so it's not exposed to the public. @@ -154,12 +154,12 @@ mod tests { pub fn compute_output_nullifiers( _self: Self, - nullifiers: [NullifierContext; N] + nullifiers: [ScopedNullifier; N] ) -> [Nullifier; N] { let mut output = [Nullifier::empty(); N]; - output[0].value = nullifiers[0].value; + output[0].value = nullifiers[0].value(); for i in 1..N { - output[i] = Nullifier { value: silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value), counter: 0, note_hash: 0 }; + output[i] = Nullifier { value: silo_nullifier(nullifiers[i].contract_address, nullifiers[i].value()), counter: 0, note_hash: 0 }; } output } @@ -182,8 +182,8 @@ mod tests { } pub fn nullify_pending_note_hash(&mut self, nullifier_index: u64, note_hash_index: u64) { - self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter; - self.previous_kernel.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).value(); + self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter(); + self.previous_kernel.new_nullifiers.storage[nullifier_index].nullifier.note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).value(); self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; } @@ -198,7 +198,7 @@ mod tests { let sorted = sort_get_sorted_hints( self.previous_kernel.new_nullifiers.storage, - |a: NullifierContext, b: NullifierContext| a.counter < b.counter + |a: ScopedNullifier, b: ScopedNullifier| a.counter() < b.counter() ); let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; @@ -336,7 +336,7 @@ mod tests { builder.add_pending_nullifier_read_request(1); let nullifier_being_read = builder.previous_kernel.new_nullifiers.storage[2]; let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter - 1; + read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); @@ -408,7 +408,7 @@ mod tests { let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; - let mut reversed_nullifiers = [NullifierContext::empty(); 10]; + let mut reversed_nullifiers = [ScopedNullifier::empty(); 10]; for i in 0..10 { reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index c561384f859..2738f531269 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -78,7 +78,7 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest }, @@ -248,9 +248,7 @@ mod tests { // Setup 2 new nullifiers on the previous kernel. builder.previous_kernel.append_new_nullifiers(2); - let previous = builder.previous_kernel.new_nullifiers.storage.map( - |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } - ); + let previous = builder.previous_kernel.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier); // Setup 2 new note hashes on the current public inputs. let current = [ 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 45ab7205c51..01abb6ea24d 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 @@ -115,7 +115,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, kernel_data::PublicKernelData, - nullifier::{Nullifier, NullifierContext}, nullifier_leaf_preimage::NullifierLeafPreimage, + nullifier::{Nullifier, ScopedNullifier}, nullifier_leaf_preimage::NullifierLeafPreimage, membership_witness::PublicDataMembershipWitness }, constants::{ @@ -123,7 +123,7 @@ mod tests { MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX }, hash::{silo_nullifier, sha256_to_field}, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, @@ -230,9 +230,7 @@ mod tests { let nullifiers = array_merge( self.previous_kernel.new_nullifiers.storage, self.previous_revertible.new_nullifiers.storage - ).map( - |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } - ); + ).map(|n: ScopedNullifier| n.nullifier); self.nullifier_non_existent_read_request_hints_builder.set_nullifiers(nullifiers); } @@ -363,18 +361,11 @@ mod tests { public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - let hash_bytes: [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] = prev_encrypted_logs_hash - .to_be_bytes(32) - .append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 32]) - .as_array(); + let hash_bytes: [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] = prev_encrypted_logs_hash.to_be_bytes(32).append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 32]).as_array(); let expected_encrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = prev_unencrypted_logs_hash - .to_be_bytes(32) - .append(unencrypted_logs_hash.to_be_bytes(32)) - .append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]) - .as_array(); + let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = prev_unencrypted_logs_hash.to_be_bytes(32).append(unencrypted_logs_hash.to_be_bytes(32)).append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]).as_array(); let expected_unencrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); } @@ -429,7 +420,7 @@ mod tests { builder.add_pending_revertible_nullifier_read_request(1); let nullifier_being_read = builder.previous_revertible.new_nullifiers.get(1); let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter - 1; + read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); 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 61c315b839a..d4ffdd52197 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 @@ -47,10 +47,7 @@ mod tests { use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ address::AztecAddress, - abis::{ - nullifier::NullifierContext, nullifier_leaf_preimage::NullifierLeafPreimage, - read_request::ReadRequestContext - }, + abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage, read_request::ReadRequestContext}, constants::NULLIFIER_TREE_HEIGHT, hash::silo_nullifier, merkle_tree::MembershipWitness, tests::merkle_tree_utils::NonEmptyMerkleTree }; @@ -71,8 +68,8 @@ mod tests { ]; global pending_values = [ - NullifierContext { value: inner_nullifiers[2], counter: 2, note_hash: 0, contract_address }, - NullifierContext { value: inner_nullifiers[3], counter: 8, note_hash: 0, contract_address }, + Nullifier { value: inner_nullifiers[2], counter: 2, note_hash: 0 }.scope(contract_address), + Nullifier { value: inner_nullifiers[3], counter: 8, note_hash: 0 }.scope(contract_address), ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, @@ -162,7 +159,7 @@ mod tests { fn test_reset_nullifier_read_requests_wrong_hinted_value() { let mut tainted_pending_values = pending_values; // Tweak the value to be something different. - tainted_pending_values[0].value += 1; + tainted_pending_values[0].nullifier.value += 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( @@ -181,7 +178,7 @@ mod tests { let pending_read = read_requests[hint.read_request_index]; let mut tainted_pending_values = pending_values; // Tweak the counter of the value to be greater than the read request. - tainted_pending_values[hint.pending_value_index].counter = pending_read.counter + 1; + tainted_pending_values[hint.pending_value_index].nullifier.counter = pending_read.counter + 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( 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 0d277770e05..9dd186a0484 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 @@ -3,7 +3,7 @@ use crate::{ nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests }; use dep::types::{ - abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext, validation_requests::ValidationRequests}, + abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier, validation_requests::ValidationRequests}, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M @@ -17,7 +17,7 @@ struct PrivateValidationRequestProcessor { pending_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, nullifier_read_request_hints: NullifierReadRequestHints, - pending_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + pending_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], nullifier_tree_root: Field, master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index d487f8f4b83..a109bdbeb78 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -1,10 +1,10 @@ -use dep::types::{abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext}, traits::is_empty}; +use dep::types::{abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier}, traits::is_empty}; pub fn verify_squashed_transient_note_hashes_and_nullifiers( note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], - nullifiers: [NullifierContext; NUM_NULLIFIERS], + nullifiers: [ScopedNullifier; NUM_NULLIFIERS], expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], - expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], + expected_nullifiers: [ScopedNullifier; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS] ) { @@ -19,13 +19,13 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers { num_note_hashes: u64, num_nullifiers: u64, note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], - nullifiers: [NullifierContext; NUM_NULLIFIERS], + nullifiers: [ScopedNullifier; NUM_NULLIFIERS], expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], - expected_nullifiers: [NullifierContext; NUM_NULLIFIERS], + expected_nullifiers: [ScopedNullifier; NUM_NULLIFIERS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS], } @@ -91,13 +94,13 @@ mod tests { ]; let nullifiers = [ - NullifierContext { value: 44, counter: 400, note_hash: 33, contract_address }, - NullifierContext { value: 55, counter: 500, note_hash: 11, contract_address }, - NullifierContext { value: 66, counter: 600, note_hash: 0, contract_address } + Nullifier { value: 44, counter: 400, note_hash: 33 }.scope(contract_address), + Nullifier { value: 55, counter: 500, note_hash: 11 }.scope(contract_address), + Nullifier { value: 66, counter: 600, note_hash: 0 }.scope(contract_address) ]; let expected_note_hashes = [note_hashes[1], ScopedNoteHash::empty(), ScopedNoteHash::empty()]; - let expected_nullifiers = [nullifiers[2], NullifierContext::empty(), NullifierContext::empty()]; + let expected_nullifiers = [nullifiers[2], ScopedNullifier::empty(), ScopedNullifier::empty()]; let transient_nullifier_indexes_for_note_hashes = [1, 3, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 3]; @@ -124,13 +127,13 @@ mod tests { ]; let nullifiers = [ - NullifierContext { value: 44, counter: 400, note_hash: 33, contract_address }, - NullifierContext { value: 55, counter: 500, note_hash: 11, contract_address }, - NullifierContext { value: 66, counter: 600, note_hash: 22, contract_address } + Nullifier { value: 44, counter: 400, note_hash: 33 }.scope(contract_address), + Nullifier { value: 55, counter: 500, note_hash: 11 }.scope(contract_address), + Nullifier { value: 66, counter: 600, note_hash: 22 }.scope(contract_address) ]; let expected_note_hashes = [ScopedNoteHash::empty(); 3]; - let expected_nullifiers = [NullifierContext::empty(); 3]; + let expected_nullifiers = [ScopedNullifier::empty(); 3]; let transient_nullifier_indexes_for_note_hashes = [1, 2, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 1]; @@ -251,7 +254,7 @@ mod tests { fn unexpected_nullifier_value() { let mut builder = TestDataBuilder::default_all_clear(); - builder.expected_nullifiers[2].value = 11; + builder.expected_nullifiers[2].nullifier.value = 11; builder.verify(); } @@ -260,7 +263,7 @@ mod tests { fn wrong_expected_nullifier_value() { let mut builder = TestDataBuilder::default(); - builder.expected_nullifiers[0].value += 1; + builder.expected_nullifiers[0].nullifier.value += 1; builder.verify(); } @@ -269,7 +272,7 @@ mod tests { fn wrong_expected_nullifier_counter() { let mut builder = TestDataBuilder::default(); - builder.expected_nullifiers[0].counter += 1; + builder.expected_nullifiers[0].nullifier.counter += 1; builder.verify(); } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr index 2e24360b272..264ff0af167 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr @@ -1,4 +1,4 @@ -use dep::types::abis::{note_hash::ScopedNoteHash, nullifier::NullifierContext}; +use dep::types::abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier}; pub fn squash_transient_note_hashes(note_hashes: [ScopedNoteHash; N]) -> [ScopedNoteHash; N] { let mut final_note_hashes = [ScopedNoteHash::empty(); N]; @@ -15,13 +15,13 @@ pub fn squash_transient_note_hashes(note_hashes: [ScopedNoteHash; N]) -> [Sco final_note_hashes } -pub fn squash_transient_nullifiers(nullifiers: [NullifierContext; N]) -> [NullifierContext; N] { - let mut final_nullifiers = [NullifierContext::empty(); N]; +pub fn squash_transient_nullifiers(nullifiers: [ScopedNullifier; N]) -> [ScopedNullifier; N] { + let mut final_nullifiers = [ScopedNullifier::empty(); N]; let mut num_nullifiers = 0; for i in 0..N { let nullifier = nullifiers[i]; - if nullifier.note_hash == 0 { + if nullifier.nullified_note_hash() == 0 { final_nullifiers[num_nullifiers] = nullifier; num_nullifiers += 1; } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index d6f21ff8326..12c19d640b1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - call_request::CallRequest, gas::Gas, note_hash::ScopedNoteHash, nullifier::NullifierContext, + call_request::CallRequest, gas::Gas, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::SideEffect }, messaging::l2_to_l1_message::ScopedL2ToL1Message @@ -13,7 +13,7 @@ use crate::constants::{ struct PrivateAccumulatedData { new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [NullifierContext; MAX_NEW_NULLIFIERS_PER_TX], + new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_TX], encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 1a4e0d95118..08597103279 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -7,7 +7,7 @@ use crate::{ private_accumulated_data::PrivateAccumulatedData, public_accumulated_data::PublicAccumulatedData, public_accumulated_data_builder::PublicAccumulatedDataBuilder }, - call_request::CallRequest, note_hash::{NoteHash, ScopedNoteHash}, nullifier::NullifierContext, + call_request::CallRequest, note_hash::{NoteHash, ScopedNoteHash}, nullifier::ScopedNullifier, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, constants::{ @@ -25,7 +25,7 @@ use crate::{ // .split_to_public: PublicKernelCircuitPublicInputs.(end,end_non_revertible) struct PrivateAccumulatedDataBuilder { new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, + new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -64,7 +64,7 @@ impl PrivateAccumulatedDataBuilder { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), + new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hash, unencrypted_logs_hash, @@ -140,7 +140,7 @@ impl PrivateAccumulatedDataBuilder { for i in 0..MAX_NEW_NULLIFIERS_PER_TX { let nullifier = self.new_nullifiers.storage[i]; let public_nullifier = nullifier.expose_to_public(); - if nullifier.counter < min_revertible_side_effect_counter { + if nullifier.counter() < min_revertible_side_effect_counter { non_revertible_builder.new_nullifiers.push(public_nullifier); if !is_empty(public_nullifier) { non_revertible_da_gas_used += DA_GAS_PER_FIELD; @@ -207,7 +207,7 @@ mod tests { abis::{ accumulated_data::private_accumulated_data_builder::PrivateAccumulatedDataBuilder, gas::Gas, call_request::CallRequest, caller_context::CallerContext, note_hash::NoteHash, - nullifier::{Nullifier, NullifierContext}, public_data_update_request::PublicDataUpdateRequest, + nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect }, address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, @@ -229,8 +229,8 @@ mod tests { ]; let non_revertible_nullifiers = [ - NullifierContext { value: 10, note_hash: 1, counter: 2, contract_address: AztecAddress::from_field(9900) }, - NullifierContext { value: 20, note_hash: 2, counter: 4, contract_address: AztecAddress::from_field(7788) } + Nullifier { value: 10, note_hash: 1, counter: 2 }.scope(contract_address), + Nullifier { value: 20, note_hash: 2, counter: 4 }.scope(contract_address) ]; let non_revertible_l2_to_l1_messages = [ @@ -262,8 +262,8 @@ mod tests { ]; let revertible_nullifiers = [ - NullifierContext { value: 30, note_hash: 3, counter: 8, contract_address: AztecAddress::from_field(9900) }, - NullifierContext { value: 40, note_hash: 4, counter: 11, contract_address: AztecAddress::from_field(5566) } + Nullifier { value: 30, note_hash: 3, counter: 8 }.scope(contract_address), + Nullifier { value: 40, note_hash: 4, counter: 11 }.scope(contract_address) ]; let revertible_l2_to_l1_messages = [ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr index 72013ecb8af..6d9cb271c3e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr @@ -1,7 +1,7 @@ use crate::{ abis::{side_effect::{Ordered, OrderedValue, Readable}, read_request::{ReadRequest, ReadRequestContext}}, - address::AztecAddress, constants::{NULLIFIER_CONTEXT_LENGTH, NULLIFIER_LENGTH}, - hash::silo_nullifier, traits::{Empty, Hash, Serialize, Deserialize} + address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH}, hash::silo_nullifier, + traits::{Empty, Hash, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader} }; struct Nullifier { @@ -55,7 +55,7 @@ impl Deserialize for Nullifier { impl Readable for Nullifier { fn assert_match_read_request(self, read_request: ReadRequestContext) { - // Public kernels output Nullifier instead of NullifierContext. + // Public kernels output Nullifier instead of ScopedNullifier. // The nullifier value has been siloed. let siloed_request_value = silo_nullifier(read_request.contract_address, read_request.value); assert_eq(self.value, siloed_request_value, "Value of the nullifier does not match read request"); @@ -66,83 +66,82 @@ impl Readable for Nullifier { } impl Nullifier { - pub fn to_context(self, contract_address: AztecAddress) -> NullifierContext { - NullifierContext { value: self.value, counter: self.counter, note_hash: self.note_hash, contract_address } + pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier { + ScopedNullifier { nullifier: self, contract_address } } } -struct NullifierContext { - value: Field, - counter: u32, - note_hash: Field, +struct ScopedNullifier { + nullifier: Nullifier, contract_address: AztecAddress, } -impl Ordered for NullifierContext { +impl Ordered for ScopedNullifier { fn counter(self) -> u32 { - self.counter + self.nullifier.counter } } -impl OrderedValue for NullifierContext { +impl OrderedValue for ScopedNullifier { fn value(self) -> Field { - self.value + self.nullifier.value } fn counter(self) -> u32 { - self.counter + self.nullifier.counter } } -impl Eq for NullifierContext { - fn eq(self, other: NullifierContext) -> bool { - (self.value == other.value) - & (self.counter == other.counter) - & (self.note_hash == other.note_hash) +impl Eq for ScopedNullifier { + fn eq(self, other: ScopedNullifier) -> bool { + (self.nullifier == other.nullifier) & (self.contract_address == other.contract_address) } } -impl Empty for NullifierContext { +impl Empty for ScopedNullifier { fn empty() -> Self { - NullifierContext { - value: 0, - counter: 0, - note_hash: 0, + ScopedNullifier { + nullifier: Nullifier::empty(), contract_address: AztecAddress::empty(), } } } -impl Serialize for NullifierContext { - fn serialize(self) -> [Field; NULLIFIER_CONTEXT_LENGTH] { - [self.value, self.counter as Field, self.note_hash, self.contract_address.to_field()] +impl Serialize for ScopedNullifier { + fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] { + array_concat(self.nullifier.serialize(), [self.contract_address.to_field()]) } } -impl Deserialize for NullifierContext { - fn deserialize(values: [Field; NULLIFIER_CONTEXT_LENGTH]) -> Self { - Self { - value: values[0], - counter: values[1] as u32, - note_hash: values[2], +impl Deserialize for ScopedNullifier { + fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self { + let mut reader = Reader::new(values); + let res = Self { + nullifier: reader.read_struct(Nullifier::deserialize), contract_address: AztecAddress::from_field(values[3]), - } + }; + reader.finish(); + res } } -impl Readable for NullifierContext { +impl Readable for ScopedNullifier { fn assert_match_read_request(self, read_request: ReadRequestContext) { - assert_eq(self.value, read_request.value, "Value of the nullifier does not match read request"); + assert_eq(self.nullifier.value, read_request.value, "Value of the nullifier does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the nullifier does not match read request"); assert( - read_request.counter > self.counter, "Read request counter must be greater than the counter of the nullifier" + read_request.counter > self.nullifier.counter, "Read request counter must be greater than the counter of the nullifier" ); } } -impl NullifierContext { +impl ScopedNullifier { + pub fn nullified_note_hash(self) -> Field { + self.nullifier.note_hash + } + pub fn expose_to_public(self) -> Nullifier { // Hide the actual counter and note hash when exposing it to the public kernel. - Nullifier { value: self.value, counter: 0, note_hash: 0 } + Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index c3f5f796bf3..edf929e239b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -165,7 +165,7 @@ global READ_REQUEST_LENGTH = 2; global NOTE_HASH_LENGTH = 2; global SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; global NULLIFIER_LENGTH = 3; -global NULLIFIER_CONTEXT_LENGTH = 4; +global SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; global SIDE_EFFECT_LENGTH = 2; global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; global TX_CONTEXT_LENGTH: u64 = 2 + GAS_SETTINGS_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 4c283cc8f94..4a70575949d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -6,7 +6,7 @@ use crate::{ global_variables::GlobalVariables, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, kernel_data::{PrivateKernelData, PublicKernelData, KernelData}, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, NullifierContext}, + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::SideEffect, @@ -39,7 +39,7 @@ struct FixtureBuilder { // Accumulated data. new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, + new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, @@ -144,9 +144,7 @@ impl FixtureBuilder { pub fn to_public_accumulated_data(self) -> PublicAccumulatedData { PublicAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), - new_nullifiers: self.new_nullifiers.storage.map( - |n: NullifierContext| Nullifier { value: n.value, counter: n.counter, note_hash: n.note_hash } - ), + new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, @@ -161,7 +159,7 @@ impl FixtureBuilder { pub fn to_combined_accumulated_data(self) -> CombinedAccumulatedData { CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: NullifierContext| n.value), + new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, @@ -271,7 +269,7 @@ impl FixtureBuilder { pub fn add_nullifier(&mut self, value: Field) { self.new_nullifiers.push( - NullifierContext { value, counter: self.next_counter(), note_hash: 0, contract_address: self.storage_contract_address } + Nullifier { value, counter: self.next_counter(), note_hash: 0 }.scope(self.storage_contract_address) ); } 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 d607f245cc2..332113a435c 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 @@ -5,13 +5,14 @@ import { type Tuple } from '@aztec/foundation/serialize'; import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { - NullifierContext, + Nullifier, type NullifierReadRequestHints, NullifierReadRequestHintsBuilder, PendingReadHint, ReadRequestContext, ReadRequestState, ReadRequestStatus, + type ScopedNullifier, SettledReadHint, } from '../structs/index.js'; import { buildNullifierReadRequestHints } from './build_nullifier_read_request_hints.js'; @@ -23,7 +24,7 @@ describe('buildNullifierReadRequestHints', () => { getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; let nullifierReadRequests: Tuple; - let nullifiers: Tuple; + let nullifiers: Tuple; let expectedHints: NullifierReadRequestHints; let numReadRequests = 0; let numPendingReads = 0; @@ -35,7 +36,7 @@ describe('buildNullifierReadRequestHints', () => { new ReadRequestContext(new Fr(value), counter, contractAddress); const makeNullifier = (value: number, counter = 1) => - new NullifierContext(new Fr(value), counter, Fr.ZERO, contractAddress); + new Nullifier(new Fr(value), counter, Fr.ZERO).scope(contractAddress); const readPendingNullifier = ({ nullifierIndex, 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 f56fbf971b9..9615ebd7f03 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 @@ -12,10 +12,10 @@ import { import { siloNullifier } from '../hash/hash.js'; import { type MembershipWitness, - type Nullifier, - NullifierContext, + Nullifier, NullifierReadRequestHintsBuilder, ReadRequestContext, + type ScopedNullifier, } from '../structs/index.js'; import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; @@ -29,14 +29,14 @@ export async function buildNullifierReadRequestHints( getNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, siloed = false, ) { const builder = new NullifierReadRequestHintsBuilder(); const numReadRequests = countAccumulatedItems(nullifierReadRequests); - const nullifierMap: Map = new Map(); + const nullifierMap: Map = new Map(); getNonEmptyItems(nullifiers).forEach((nullifier, index) => { const value = nullifier.value.toBigInt(); const arr = nullifierMap.get(value) ?? []; @@ -85,9 +85,9 @@ export function buildSiloedNullifierReadRequestHints( MAX_NULLIFIER_READ_REQUESTS_PER_TX, ); - const nullifierContexts = nullifiers.map( - n => new NullifierContext(n.value, n.counter, n.noteHash, AztecAddress.ZERO), - ) as Tuple; + const scopedNullifiers = nullifiers.map(n => + new Nullifier(n.value, n.counter, n.noteHash).scope(AztecAddress.ZERO), + ) as Tuple; - return buildNullifierReadRequestHints(oracle, siloedReadRequests, nullifierContexts, true); + return buildNullifierReadRequestHints(oracle, siloedReadRequests, scopedNullifiers, true); } diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index dc92fb636aa..783ea56c885 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, NoteHash, NullifierContext, type ScopedNoteHash } from '@aztec/circuits.js'; +import { AztecAddress, Fr, NoteHash, Nullifier, type ScopedNoteHash, type ScopedNullifier } from '@aztec/circuits.js'; import { buildTransientDataHints } from './build_transient_data_hints.js'; @@ -6,7 +6,7 @@ describe('buildTransientDataHints', () => { const contractAddress = AztecAddress.fromBigInt(987654n); let noteHashes: ScopedNoteHash[]; - let nullifiers: NullifierContext[]; + let nullifiers: ScopedNullifier[]; beforeEach(() => { noteHashes = [ @@ -15,10 +15,10 @@ describe('buildTransientDataHints', () => { new NoteHash(new Fr(33), 300).scope(500, contractAddress), ]; nullifiers = [ - new NullifierContext(new Fr(44), 400, new Fr(0), contractAddress), - new NullifierContext(new Fr(55), 500, new Fr(33), contractAddress), - new NullifierContext(new Fr(66), 600, new Fr(0), contractAddress), - new NullifierContext(new Fr(77), 700, new Fr(11), contractAddress), + new Nullifier(new Fr(44), 400, new Fr(0)).scope(contractAddress), + new Nullifier(new Fr(55), 500, new Fr(33)).scope(contractAddress), + new Nullifier(new Fr(66), 600, new Fr(0)).scope(contractAddress), + new Nullifier(new Fr(77), 700, new Fr(11)).scope(contractAddress), ]; }); @@ -34,7 +34,7 @@ describe('buildTransientDataHints', () => { }); it('throws if note hash does not match', () => { - nullifiers[1].noteHash = new Fr(11); + nullifiers[1].nullifier.noteHash = new Fr(11); expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow('Hinted note hash does not match.'); }); diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts index adb277f6979..a9664d6e5ce 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts @@ -1,10 +1,10 @@ -import { type NullifierContext, type ScopedNoteHash, countAccumulatedItems } from '@aztec/circuits.js'; +import { type ScopedNoteHash, type ScopedNullifier, countAccumulatedItems } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildTransientDataHints( noteHashes: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, noteHashesLength: NOTE_HASHES_LEN = noteHashes.length as NOTE_HASHES_LEN, nullifiersLength: NULLIFIERS_LEN = nullifiers.length as NULLIFIERS_LEN, ): [Tuple, Tuple] { @@ -31,7 +31,7 @@ export function buildTransientDataHints, + public newNullifiers: Tuple, /** * All the new L2 to L1 messages created in this transaction. */ @@ -92,7 +92,7 @@ export class PrivateAccumulatedData { const reader = BufferReader.asReader(buffer); return new PrivateAccumulatedData( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), @@ -115,7 +115,7 @@ export class PrivateAccumulatedData { static empty() { return new PrivateAccumulatedData( makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext.empty), + makeTuple(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index 9df24b12970..36ecd40f5c7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -11,7 +11,7 @@ import { import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; import { ScopedNoteHash } from '../note_hash.js'; -import { NullifierContext } from '../nullifier.js'; +import { ScopedNullifier } from '../nullifier.js'; import { type NoteHashReadRequestHints, type NullifierReadRequestHints, @@ -24,7 +24,7 @@ import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelTailOutputs { constructor( public noteHashes: Tuple, - public nullifiers: Tuple, + public nullifiers: Tuple, ) {} toBuffer() { @@ -35,7 +35,7 @@ export class PrivateKernelTailOutputs { const reader = BufferReader.asReader(buffer); return new PrivateKernelTailOutputs( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), ); } } @@ -74,7 +74,7 @@ export class PrivateKernelTailHints { /** * The sorted new nullifiers. Maps original to sorted. */ - public sortedNewNullifiers: Tuple, + public sortedNewNullifiers: Tuple, /** * The sorted new nullifiers indexes. */ @@ -130,7 +130,7 @@ export class PrivateKernelTailHints { reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierContext), + reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), reader.readNumbers(MAX_ENCRYPTED_LOGS_PER_TX), diff --git a/yarn-project/circuits.js/src/structs/nullifier.ts b/yarn-project/circuits.js/src/structs/nullifier.ts index fd2fd126396..7f1e73477e1 100644 --- a/yarn-project/circuits.js/src/structs/nullifier.ts +++ b/yarn-project/circuits.js/src/structs/nullifier.ts @@ -36,48 +36,54 @@ export class Nullifier implements Ordered { toString(): string { return `value=${this.value} counter=${this.counter} noteHash=${this.noteHash}`; } + + scope(contractAddress: AztecAddress) { + return new ScopedNullifier(this, contractAddress); + } } -export class NullifierContext implements Ordered { - constructor(public value: Fr, public counter: number, public noteHash: Fr, public contractAddress: AztecAddress) {} +export class ScopedNullifier implements Ordered { + constructor(public nullifier: Nullifier, public contractAddress: AztecAddress) {} + + get counter() { + return this.nullifier.counter; + } + + get value() { + return this.nullifier.value; + } + + get nullifiedNoteHash() { + return this.nullifier.noteHash; + } toFields(): Fr[] { - return [this.value, new Fr(this.counter), this.noteHash, this.contractAddress.toField()]; + return [...this.nullifier.toFields(), this.contractAddress.toField()]; } static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new NullifierContext( - reader.readField(), - reader.readU32(), - reader.readField(), - AztecAddress.fromField(reader.readField()), - ); + return new ScopedNullifier(reader.readObject(Nullifier), AztecAddress.fromField(reader.readField())); } isEmpty() { - return this.value.isZero() && !this.counter && this.noteHash.isZero() && this.contractAddress.isZero(); + return this.nullifier.isEmpty() && this.contractAddress.isZero(); } static empty() { - return new NullifierContext(Fr.zero(), 0, Fr.zero(), AztecAddress.ZERO); + return new ScopedNullifier(Nullifier.empty(), AztecAddress.ZERO); } toBuffer(): Buffer { - return serializeToBuffer(this.value, this.counter, this.noteHash, this.contractAddress); + return serializeToBuffer(this.nullifier, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new NullifierContext( - Fr.fromBuffer(reader), - reader.readNumber(), - Fr.fromBuffer(reader), - AztecAddress.fromBuffer(reader), - ); + return new ScopedNullifier(Nullifier.fromBuffer(reader), AztecAddress.fromBuffer(reader)); } toString(): string { - return `value=${this.value} counter=${this.counter} noteHash=${this.noteHash} contractAddress=${this.contractAddress}`; + return `nullifier=${this.nullifier} contractAddress=${this.contractAddress}`; } } 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 816301c724c..463b31940e0 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -55,7 +55,6 @@ import { NoteHash, type NoteHashReadRequestHints, Nullifier, - NullifierContext, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, type NullifierLeafPreimage, @@ -109,6 +108,7 @@ import { RootRollupPublicInputs, ScopedL2ToL1Message, ScopedNoteHash, + ScopedNullifier, type SettledReadHint, SideEffect, type StateDiffHints, @@ -143,7 +143,6 @@ import { type Field as NoirField, type GrumpkinPoint as NoirPoint, type NoteHash as NoteHashNoir, - type NullifierContext as NullifierContextNoir, type NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, type NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, type Nullifier as NullifierNoir, @@ -159,6 +158,7 @@ import { type RollupValidationRequests as RollupValidationRequestsNoir, type ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, type ScopedNoteHash as ScopedNoteHashNoir, + type ScopedNullifier as ScopedNullifierNoir, type SideEffect as SideEffectNoir, type TxContext as TxContextNoir, type TxRequest as TxRequestNoir, @@ -591,20 +591,16 @@ function mapNullifierFromNoir(nullifier: NullifierNoir) { ); } -function mapNullifierContextToNoir(nullifier: NullifierContext): NullifierContextNoir { +function mapScopedNullifierToNoir(nullifier: ScopedNullifier): ScopedNullifierNoir { return { - value: mapFieldToNoir(nullifier.value), - counter: mapNumberToNoir(nullifier.counter), - note_hash: mapFieldToNoir(nullifier.noteHash), + nullifier: mapNullifierToNoir(nullifier.nullifier), contract_address: mapAztecAddressToNoir(nullifier.contractAddress), }; } -function mapNullifierContextFromNoir(nullifier: NullifierContextNoir) { - return new NullifierContext( - mapFieldFromNoir(nullifier.value), - mapNumberFromNoir(nullifier.counter), - mapFieldFromNoir(nullifier.note_hash), +function mapScopedNullifierFromNoir(nullifier: ScopedNullifierNoir) { + return new ScopedNullifier( + mapNullifierFromNoir(nullifier.nullifier), mapAztecAddressFromNoir(nullifier.contract_address), ); } @@ -1094,7 +1090,7 @@ export function mapPrivateAccumulatedDataFromNoir( ): PrivateAccumulatedData { return new PrivateAccumulatedData( mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapScopedNoteHashFromNoir), - mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierContextFromNoir), + mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapScopedNullifierFromNoir), mapTupleFromNoir( privateAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, @@ -1124,7 +1120,7 @@ export function mapPrivateAccumulatedDataFromNoir( export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): PrivateAccumulatedDataNoir { return { new_note_hashes: mapTuple(data.newNoteHashes, mapScopedNoteHashToNoir), - new_nullifiers: mapTuple(data.newNullifiers, mapNullifierContextToNoir), + new_nullifiers: mapTuple(data.newNullifiers, mapScopedNullifierToNoir), new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapScopedL2ToL1MessageToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapSideEffectToNoir), @@ -1462,7 +1458,7 @@ export function mapPrivateKernelInnerCircuitPrivateInputsToNoir( function mapPrivateKernelTailOutputsToNoir(inputs: PrivateKernelTailOutputs): PrivateKernelTailOutputsNoir { return { note_hashes: mapTuple(inputs.noteHashes, mapScopedNoteHashToNoir), - nullifiers: mapTuple(inputs.nullifiers, mapNullifierContextToNoir), + nullifiers: mapTuple(inputs.nullifiers, mapScopedNullifierToNoir), }; } @@ -1478,7 +1474,7 @@ function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): Privat master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapScopedNoteHashToNoir), sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), - sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapNullifierContextToNoir), + sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapScopedNullifierToNoir), sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapSideEffectToNoir), sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index 13651f02924..1346349ae40 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -9,11 +9,11 @@ import { type MAX_UNENCRYPTED_LOGS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, - type NullifierContext, type NullifierKeyValidationRequestContext, type PrivateKernelCircuitPublicInputs, PrivateKernelTailHints, type ReadRequestContext, + type ScopedNullifier, type SideEffect, type SideEffectType, buildNoteHashReadRequestHints, @@ -50,7 +50,7 @@ function sortSideEffects( function getNullifierReadRequestHints( nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, oracle: ProvingDataOracle, ) { const getNullifierMembershipWitness = async (nullifier: Fr) => { diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts index 5e46e4162a0..91d8cd8be0a 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts @@ -1,16 +1,16 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, - NullifierContext, PrivateKernelTailOutputs, ScopedNoteHash, + ScopedNullifier, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelTailOutputs( prevNoteHashes: Tuple, - prevNullifiers: Tuple, + prevNullifiers: Tuple, ) { // Propagate note hashes that are not linked to a nullifier. // Note that note hashes can't link to the first nullifier (counter == 0). @@ -21,8 +21,8 @@ export function buildPrivateKernelTailOutputs( ); const nullifiers = padArrayEnd( - prevNullifiers.filter(n => n.noteHash.isZero()), - NullifierContext.empty(), + prevNullifiers.filter(n => n.nullifiedNoteHash.isZero()), + ScopedNullifier.empty(), MAX_NEW_NULLIFIERS_PER_TX, ); From 52b4e023e9710abbecf8a7aaaac3cc42dc0af49e Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 7 May 2024 23:57:13 +0000 Subject: [PATCH 10/13] Rename ReadRequestContext to ScopedReadRequest. --- ...e_kernel_circuit_public_inputs_composer.nr | 4 +- .../src/private_kernel_init.nr | 30 ++++------ .../src/private_kernel_inner.nr | 16 +++-- .../src/private_kernel_tail.nr | 2 +- .../src/private_kernel_tail_to_public.nr | 2 +- .../crates/public-kernel-lib/src/common.nr | 6 +- .../src/public_kernel_app_logic.nr | 16 +++-- .../src/public_kernel_setup.nr | 16 +++-- .../src/public_kernel_tail.nr | 2 +- .../src/note_hash_read_request_reset.nr | 18 +++--- .../src/nullifier_read_request_reset.nr | 16 ++--- .../public_validation_request_processor.nr | 2 +- .../src/reset/non_existent_read_request.nr | 55 ++++++++--------- .../src/reset/read_request.nr | 33 +++++----- .../crates/types/src/abis/note_hash.nr | 10 ++-- .../types/src/abis/note_hash_leaf_preimage.nr | 6 +- .../crates/types/src/abis/nullifier.nr | 14 ++--- .../types/src/abis/nullifier_leaf_preimage.nr | 6 +- .../crates/types/src/abis/read_request.nr | 60 +++++++++++-------- .../crates/types/src/abis/side_effect.nr | 4 +- .../validation_requests.nr | 8 +-- .../validation_requests_builder.nr | 8 +-- .../crates/types/src/tests/fixture_builder.nr | 20 +++---- ...build_note_hash_read_request_hints.test.ts | 13 ++-- .../build_note_hash_read_request_hints.ts | 6 +- ...er_non_existent_read_request_hints.test.ts | 11 +++- ...llifier_non_existent_read_request_hints.ts | 4 +- ...build_nullifier_read_request_hints.test.ts | 9 +-- .../build_nullifier_read_request_hints.ts | 13 ++-- .../circuits.js/src/structs/read_request.ts | 45 +++++++------- .../src/structs/validation_requests.ts | 20 +++---- .../circuits.js/src/tests/factories.ts | 12 ++-- .../src/type_conversion.ts | 37 +++++------- .../build_private_kernel_tail_hints.ts | 4 +- .../simulator/src/public/hints_builder.ts | 6 +- 35 files changed, 266 insertions(+), 268 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index 45f859e54e7..6efd4d56c8e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -117,7 +117,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..read_requests.len() { let request = read_requests[i]; if !is_empty(request) { - self.public_inputs.validation_requests.note_hash_read_requests.push(request.to_context(source.storage_contract_address)); + self.public_inputs.validation_requests.note_hash_read_requests.push(request.scope(source.storage_contract_address)); } } } @@ -127,7 +127,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..nullifier_read_requests.len() { let request = nullifier_read_requests[i]; if !is_empty(request) { - self.public_inputs.validation_requests.nullifier_read_requests.push(request.to_context(source.storage_contract_address)); + self.public_inputs.validation_requests.nullifier_read_requests.push(request.scope(source.storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index fd12d41c650..cb5aca1f969 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -368,15 +368,13 @@ mod tests { let end_note_hash_read_requests = public_inputs.validation_requests.note_hash_read_requests; assert_eq(array_length(end_note_hash_read_requests), 2); - let request_context = end_note_hash_read_requests[0]; - assert_eq(request_context.value, request_0.value); - assert_eq(request_context.counter, request_0.counter); - assert_eq(request_context.contract_address, storage_contract_address); - - let request_context = end_note_hash_read_requests[1]; - assert_eq(request_context.value, request_1.value); - assert_eq(request_context.counter, request_1.counter); - assert_eq(request_context.contract_address, storage_contract_address); + let request = end_note_hash_read_requests[0]; + assert_eq(request.read_request, request_0); + assert_eq(request.contract_address, storage_contract_address); + + let request = end_note_hash_read_requests[1]; + assert_eq(request.read_request, request_1); + assert_eq(request.contract_address, storage_contract_address); } #[test] @@ -394,15 +392,13 @@ mod tests { let end_nullifier_read_requests = public_inputs.validation_requests.nullifier_read_requests; assert_eq(array_length(end_nullifier_read_requests), 2); - let request_context = end_nullifier_read_requests[0]; - assert_eq(request_context.value, request_0.value); - assert_eq(request_context.counter, request_0.counter); - assert_eq(request_context.contract_address, storage_contract_address); + let request = end_nullifier_read_requests[0]; + assert_eq(request.read_request, request_0); + assert_eq(request.contract_address, storage_contract_address); - let request_context = end_nullifier_read_requests[1]; - assert_eq(request_context.value, request_1.value); - assert_eq(request_context.counter, request_1.counter); - assert_eq(request_context.contract_address, storage_contract_address); + let request = end_nullifier_read_requests[1]; + assert_eq(request.read_request, request_1); + assert_eq(request.contract_address, storage_contract_address); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 2af895bb398..6a291bafbfa 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -571,15 +571,13 @@ mod tests { assert_eq(end_note_hash_read_requests[0], prev_requests.storage[0]); assert_eq(end_note_hash_read_requests[1], prev_requests.storage[1]); - let request_context = end_note_hash_read_requests[2]; - assert_eq(request_context.value, cur_requests[0].value); - assert_eq(request_context.counter, cur_requests[0].counter); - assert_eq(request_context.contract_address, cur_storage_contract_address); - - let request_context = end_note_hash_read_requests[3]; - assert_eq(request_context.value, cur_requests[1].value); - assert_eq(request_context.counter, cur_requests[1].counter); - assert_eq(request_context.contract_address, cur_storage_contract_address); + let request = end_note_hash_read_requests[2]; + assert_eq(request.read_request, cur_requests[0]); + assert_eq(request.contract_address, cur_storage_contract_address); + + let request = end_note_hash_read_requests[3]; + assert_eq(request.read_request, cur_requests[1]); + assert_eq(request.contract_address, cur_storage_contract_address); } #[test] 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 48be18e3dee..2471caad0be 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 @@ -388,7 +388,7 @@ mod tests { builder.add_pending_nullifier_read_request(1); let nullifier_being_read = builder.previous_kernel.new_nullifiers.storage[2]; let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter() - 1; + read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); 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 d56e45296ff..a16c3ea41ba 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 @@ -336,7 +336,7 @@ mod tests { builder.add_pending_nullifier_read_request(1); let nullifier_being_read = builder.previous_kernel.new_nullifiers.storage[2]; let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter() - 1; + read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index adf8f2a1952..83d5770a806 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -4,7 +4,7 @@ use dep::types::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputsBuilder, kernel_data::PublicKernelData, note_hash::NoteHash, nullifier::Nullifier, public_call_data::PublicCallData, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - read_request::ReadRequestContext, side_effect::SideEffect, global_variables::GlobalVariables, + side_effect::SideEffect, global_variables::GlobalVariables, combined_constant_data::CombinedConstantData }, address::AztecAddress, @@ -324,7 +324,7 @@ fn propagate_nullifier_read_requests( for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL { let request = nullifier_read_requests[i]; if !is_empty(request) { - circuit_outputs.validation_requests.nullifier_read_requests.push(request.to_context(storage_contract_address)); + circuit_outputs.validation_requests.nullifier_read_requests.push(request.scope(storage_contract_address)); } } } @@ -340,7 +340,7 @@ fn propagate_nullifier_non_existent_read_requests( for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL { let request = nullifier_non_existent_read_requests[i]; if !is_empty(request) { - circuit_outputs.validation_requests.nullifier_non_existent_read_requests.push(request.to_context(storage_contract_address)); + circuit_outputs.validation_requests.nullifier_non_existent_read_requests.push(request.scope(storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 2738f531269..6fd4e359211 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -439,15 +439,13 @@ mod tests { let end_requests = public_inputs.validation_requests.nullifier_non_existent_read_requests; assert_eq(array_length(end_requests), 2); - let request_context = end_requests[0]; - assert_eq(request_context.value, request_0.value); - assert_eq(request_context.counter, request_0.counter); - assert_eq(request_context.contract_address, storage_contract_address); - - let request_context = end_requests[1]; - assert_eq(request_context.value, request_1.value); - assert_eq(request_context.counter, request_1.counter); - assert_eq(request_context.contract_address, storage_contract_address); + let request = end_requests[0]; + assert_eq(request.read_request, request_0); + assert_eq(request.contract_address, storage_contract_address); + + let request = end_requests[1]; + assert_eq(request.read_request, request_1); + assert_eq(request.contract_address, storage_contract_address); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 57baeb5d851..248c89c0b7a 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -483,15 +483,13 @@ mod tests { let end_requests = public_inputs.validation_requests.nullifier_non_existent_read_requests; assert_eq(array_length(end_requests), 2); - let request_context = end_requests[0]; - assert_eq(request_context.value, request_0.value); - assert_eq(request_context.counter, request_0.counter); - assert_eq(request_context.contract_address, storage_contract_address); - - let request_context = end_requests[1]; - assert_eq(request_context.value, request_1.value); - assert_eq(request_context.counter, request_1.counter); - assert_eq(request_context.contract_address, storage_contract_address); + let request = end_requests[0]; + assert_eq(request.read_request, request_0); + assert_eq(request.contract_address, storage_contract_address); + + let request = end_requests[1]; + assert_eq(request.read_request, request_1); + assert_eq(request.contract_address, storage_contract_address); } #[test(should_fail_with="Public call cannot be reverted")] 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 01abb6ea24d..531c450b680 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 @@ -420,7 +420,7 @@ mod tests { builder.add_pending_revertible_nullifier_read_request(1); let nullifier_being_read = builder.previous_revertible.new_nullifiers.get(1); let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); - read_request.counter = nullifier_being_read.counter() - 1; + read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); builder.failed(); 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 688c83ea927..21bc6dce99e 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 @@ -49,7 +49,7 @@ mod tests { address::AztecAddress, abis::{ membership_witness::NoteHashMembershipWitness, note_hash::NoteHash, - note_hash_leaf_preimage::NoteHashLeafPreimage, read_request::ReadRequestContext + note_hash_leaf_preimage::NoteHashLeafPreimage, read_request::ReadRequest }, constants::NOTE_HASH_TREE_HEIGHT, hash::silo_note_hash, tests::merkle_tree_utils::NonEmptyMerkleTree @@ -64,11 +64,11 @@ mod tests { // Create 5 read requests. 0 and 3 are reading settled note hashes. 1, 2 and 4 are reading pending note hashes. // TODO(#2847): Read request values for settled note hashes shouldn't have been siloed by apps. global read_requests = [ - ReadRequestContext { value: note_hashes[1], counter: 11, contract_address }, // settled - ReadRequestContext { value: inner_note_hashes[3], counter: 13, contract_address }, // pending - ReadRequestContext { value: inner_note_hashes[2], counter: 39, contract_address }, // pending - ReadRequestContext { value: note_hashes[0], counter: 46, contract_address }, // settled - ReadRequestContext { value: inner_note_hashes[3], counter: 78, contract_address }, // pending + ReadRequest { value: note_hashes[1], counter: 11 }.scope(contract_address), // settled + ReadRequest { value: inner_note_hashes[3], counter: 13 }.scope(contract_address), // pending + ReadRequest { value: inner_note_hashes[2], counter: 39 }.scope(contract_address), // pending + ReadRequest { value: note_hashes[0], counter: 46 }.scope(contract_address), // settled + ReadRequest { value: inner_note_hashes[3], counter: 78 }.scope(contract_address), // pending ]; global pending_values = [ @@ -180,7 +180,7 @@ mod tests { let pending_read = read_requests[hint.read_request_index]; let mut tainted_pending_values = pending_values; // Tweak the counter of the value to be greater than the read request. - tainted_pending_values[hint.pending_value_index].note_hash.counter = pending_read.counter + 1; + tainted_pending_values[hint.pending_value_index].note_hash.counter = pending_read.counter() + 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( @@ -199,7 +199,7 @@ mod tests { let pending_read = read_requests[hint.read_request_index]; let mut tainted_pending_values = pending_values; // Tweak the nullifier counter to be less than the read request. - tainted_pending_values[hint.pending_value_index].nullifier_counter = pending_read.counter - 1; + tainted_pending_values[hint.pending_value_index].nullifier_counter = pending_read.counter() - 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( @@ -219,7 +219,7 @@ mod tests { let mut tained_read_requests = read_requests; let hint = settled_read_hints[0]; // Tweak the value of the first settled read to be something different. - tained_read_requests[hint.read_request_index].value += 1; + tained_read_requests[hint.read_request_index].read_request.value += 1; let _ = reset_read_requests( tained_read_requests, 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 d4ffdd52197..e7363f828c4 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 @@ -47,7 +47,7 @@ mod tests { use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ address::AztecAddress, - abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage, read_request::ReadRequestContext}, + abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage, read_request::ReadRequest}, constants::NULLIFIER_TREE_HEIGHT, hash::silo_nullifier, merkle_tree::MembershipWitness, tests::merkle_tree_utils::NonEmptyMerkleTree }; @@ -60,11 +60,11 @@ mod tests { // Create 5 read requests. 0 and 3 are reading settled nullifiers. 1, 2 and 4 are reading pending nullifiers. global read_requests = [ - ReadRequestContext { value: inner_nullifiers[1], counter: 11, contract_address }, // settled - ReadRequestContext { value: inner_nullifiers[3], counter: 13, contract_address }, // pending - ReadRequestContext { value: inner_nullifiers[2], counter: 39, contract_address }, // pending - ReadRequestContext { value: inner_nullifiers[0], counter: 46, contract_address }, // settled - ReadRequestContext { value: inner_nullifiers[3], counter: 78, contract_address }, // pending + ReadRequest { value: inner_nullifiers[1], counter: 11 }.scope(contract_address), // settled + ReadRequest { value: inner_nullifiers[3], counter: 13 }.scope(contract_address), // pending + ReadRequest { value: inner_nullifiers[2], counter: 39 }.scope(contract_address), // pending + ReadRequest { value: inner_nullifiers[0], counter: 46 }.scope(contract_address), // settled + ReadRequest { value: inner_nullifiers[3], counter: 78 }.scope(contract_address), // pending ]; global pending_values = [ @@ -178,7 +178,7 @@ mod tests { let pending_read = read_requests[hint.read_request_index]; let mut tainted_pending_values = pending_values; // Tweak the counter of the value to be greater than the read request. - tainted_pending_values[hint.pending_value_index].nullifier.counter = pending_read.counter + 1; + tainted_pending_values[hint.pending_value_index].nullifier.counter = pending_read.counter() + 1; let (settled_read_hints, tree_root) = get_settled_read_hints(); let _ = reset_read_requests( @@ -198,7 +198,7 @@ mod tests { let mut tained_read_requests = read_requests; let hint = settled_read_hints[0]; // Tweak the value of the first settled read to be something different. - tained_read_requests[hint.read_request_index].value += 1; + tained_read_requests[hint.read_request_index].read_request.value += 1; let _ = reset_read_requests( tained_read_requests, 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 a3fd6a84cce..a25b760e1d4 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 @@ -88,7 +88,7 @@ impl PublicValidationRequestProcessor { for i in 0..read_requests.len() { let read_request = read_requests[i]; if !is_empty(read_request) { - read_requests[i].value = silo_nullifier(read_request.contract_address, read_request.value); + read_requests[i].read_request.value = silo_nullifier(read_request.contract_address, read_request.value()); } } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr index 10feabce540..ec1c8afde44 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr @@ -1,5 +1,5 @@ use dep::types::{ - abis::{side_effect::OrderedValue, read_request::ReadRequestContext}, + abis::{side_effect::OrderedValue, read_request::ScopedReadRequest}, merkle_tree::{assert_check_non_membership, IndexedTreeLeafPreimage, MembershipWitness}, traits::{Empty, is_empty} }; @@ -10,28 +10,28 @@ trait NonMembershipHint where LEAF_PREIMAGE: Indexed } fn check_no_matching_pending_value( - read_request: ReadRequestContext, + read_request: ScopedReadRequest, sorted_pending_values: BoundedVec, next_value_index: u64 ) -> bool where T: OrderedValue { if next_value_index == sorted_pending_values.len() { let highest_value = sorted_pending_values.get_unchecked(sorted_pending_values.len() - 1).value(); - highest_value.lt(read_request.value) + highest_value.lt(read_request.value()) } else { let next_value = sorted_pending_values.get_unchecked(next_value_index).value(); - let is_less_than_next = read_request.value.lt(next_value); + let is_less_than_next = read_request.value().lt(next_value); let is_greater_than_prev = if next_value_index == 0 { true } else { let prev_value = sorted_pending_values.get_unchecked(next_value_index - 1).value(); - prev_value.lt(read_request.value) + prev_value.lt(read_request.value()) }; is_less_than_next & is_greater_than_prev } } fn check_is_read_before_pending_value( - read_request: ReadRequestContext, + read_request: ScopedReadRequest, sorted_pending_values: BoundedVec, next_value_index: u64 ) -> bool where T: OrderedValue { @@ -39,8 +39,8 @@ fn check_is_read_before_pending_value( false } else { let pending = sorted_pending_values.get_unchecked(next_value_index); - if pending.value() == read_request.value { - assert(read_request.counter < pending.counter(), "Value exists in pending set"); + if pending.value() == read_request.value() { + assert(read_request.counter() < pending.counter(), "Value exists in pending set"); true } else { false @@ -52,7 +52,7 @@ fn check_is_read_before_pending_value( // Non existent read requests can only be verified at the end, after all pending values are present. // The values in read_requests and in sorted_pending_values should've been siloed before calling this. pub fn reset_non_existent_read_requests( - siloed_read_requests: [ReadRequestContext; N], + siloed_read_requests: [ScopedReadRequest; N], non_membership_hints: [NON_MEMBERSHIP_HINT; N], tree_root: Field, sorted_pending_values: BoundedVec, @@ -67,7 +67,7 @@ pub fn reset_non_existent_read_requests where LEAF_PREIMAGE: LeafPreim // - https://discourse.aztec.network/t/to-read-or-not-to-read/178 // - https://discourse.aztec.network/t/spending-notes-which-havent-yet-been-inserted/180 fn validate_pending_read_requests( - read_requests: [ReadRequestContext; READ_REQUEST_LEN], + read_requests: [ScopedReadRequest; READ_REQUEST_LEN], pending_values: [T; PENDING_VALUE_LEN], hints: [PendingReadHint; NUM_PENDING_READS] ) where T: Readable { @@ -76,7 +76,7 @@ fn validate_pending_read_requests( - read_requests: [ReadRequestContext; READ_REQUEST_LEN], + read_requests: [ScopedReadRequest; READ_REQUEST_LEN], hints: [H; NUM_SETTLED_READS], tree_root: Field ) where @@ -97,11 +97,11 @@ fn validate_settled_read_requests( - read_requests: [ReadRequestContext; READ_REQUEST_LEN], + read_requests: [ScopedReadRequest; READ_REQUEST_LEN], read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], pending_read_hints: [T; NUM_PENDING_READS], settled_read_hints: [S; NUM_SETTLED_READS] -) -> BoundedVec where T: ReadValueHint, S: ReadValueHint { +) -> BoundedVec where T: ReadValueHint, S: ReadValueHint { let mut propagated_read_requests = BoundedVec::new(); for i in 0..READ_REQUEST_LEN { let read_request = read_requests[i]; @@ -124,13 +124,13 @@ fn propagate_unverified_read_requests( - read_requests: [ReadRequestContext; READ_REQUEST_LEN], + read_requests: [ScopedReadRequest; READ_REQUEST_LEN], pending_values: [P; PENDING_VALUE_LEN], read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], pending_read_hints: [PendingReadHint; NUM_PENDING_READS], settled_read_hints: [H; NUM_SETTLED_READS], tree_root: Field -) -> BoundedVec where +) -> BoundedVec where P: Readable, H: SettledReadHint + ReadValueHint, LEAF_PREIMAGE: LeafPreimage + Readable { @@ -153,7 +153,8 @@ mod tests { validate_settled_read_requests }; use dep::types::{ - address::AztecAddress, abis::{read_request::ReadRequestContext, side_effect::Readable}, + address::AztecAddress, + abis::{read_request::{ReadRequest, ScopedReadRequest}, side_effect::Readable}, merkle_tree::{LeafPreimage, MembershipWitness}, tests::merkle_tree_utils::NonEmptyMerkleTree, traits::Empty }; @@ -168,8 +169,8 @@ mod tests { } impl Readable for TestValue { - fn assert_match_read_request(self, read_request: ReadRequestContext) { - let siloed_value = silo_test_value(read_request.value); + fn assert_match_read_request(self, read_request: ScopedReadRequest) { + let siloed_value = silo_test_value(read_request.value()); assert_eq(self.value, siloed_value, "Hinted test value does not match"); } } @@ -197,8 +198,8 @@ mod tests { } impl Readable for TestLeafPreimage { - fn assert_match_read_request(self, read_request: ReadRequestContext) { - let siloed_value = silo_test_value(read_request.value); + fn assert_match_read_request(self, read_request: ScopedReadRequest) { + let siloed_value = silo_test_value(read_request.value()); assert_eq(siloed_value, self.value, "Provided leaf preimage is not for target value"); } } @@ -241,10 +242,10 @@ mod tests { // Create 4 read requests. 0 and 3 are reading settled values. 1 and 2 are reading pending values. global read_requests = [ - ReadRequestContext { value: values[1], counter: 11, contract_address }, // settled - ReadRequestContext { value: values[3], counter: 13, contract_address }, // pending - ReadRequestContext { value: values[2], counter: 39, contract_address }, // pending - ReadRequestContext { value: values[0], counter: 46, contract_address }, // settled + ReadRequest { value: values[1], counter: 11 }.scope(contract_address), // settled + ReadRequest { value: values[3], counter: 13, }.scope(contract_address), // pending + ReadRequest { value: values[2], counter: 39, }.scope(contract_address), // pending + ReadRequest { value: values[0], counter: 46, }.scope(contract_address), // settled ]; global pending_values = [ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index f32d9398d94..53a248718c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -1,5 +1,5 @@ use crate::{ - abis::read_request::ReadRequestContext, address::AztecAddress, + abis::read_request::ScopedReadRequest, address::AztecAddress, abis::side_effect::{Ordered, OrderedValue, Readable}, constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader} @@ -107,14 +107,14 @@ impl Deserialize for ScopedNoteHash { } impl Readable for ScopedNoteHash { - fn assert_match_read_request(self, read_request: ReadRequestContext) { - assert_eq(self.note_hash.value, read_request.value, "Value of the note hash does not match read request"); + fn assert_match_read_request(self, read_request: ScopedReadRequest) { + assert_eq(self.note_hash.value, read_request.value(), "Value of the note hash does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the note hash does not match read request"); assert( - read_request.counter > self.note_hash.counter, "Read request counter must be greater than the counter of the note hash" + read_request.counter() > self.note_hash.counter, "Read request counter must be greater than the counter of the note hash" ); assert( - (self.nullifier_counter == 0) | (read_request.counter < self.nullifier_counter), "Read request counter must be less than the nullifier counter of the note hash" + (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), "Read request counter must be less than the nullifier counter of the note hash" ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr index 5c9cf6ad487..031325e6430 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr @@ -1,7 +1,7 @@ global NOTE_HASH_LEAF_PREIMAGE_LENGTH: u64 = 1; use crate::{ - abis::{read_request::ReadRequestContext, side_effect::Readable}, hash::silo_note_hash, + abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::silo_note_hash, merkle_tree::leaf_preimage::LeafPreimage, traits::{Empty, Hash} }; @@ -28,11 +28,11 @@ impl LeafPreimage for NoteHashLeafPreimage { } impl Readable for NoteHashLeafPreimage { - fn assert_match_read_request(self, read_request: ReadRequestContext) { + fn assert_match_read_request(self, read_request: ScopedReadRequest) { // TODO(#2847): Read request value shouldn't have been siloed by apps. // let siloed_value = silo_note_hash(read_request.contract_address, read_request.value); // assert_eq(self.value, siloed_value, "Value of the note hash leaf does not match read request"); - assert_eq(self.value, read_request.value, "Value of the note hash leaf does not match read request"); + assert_eq(self.value, read_request.value(), "Value of the note hash leaf does not match read request"); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr index 6d9cb271c3e..da4c140d43d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr @@ -1,5 +1,5 @@ use crate::{ - abis::{side_effect::{Ordered, OrderedValue, Readable}, read_request::{ReadRequest, ReadRequestContext}}, + abis::{side_effect::{Ordered, OrderedValue, Readable}, read_request::ScopedReadRequest}, address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH}, hash::silo_nullifier, traits::{Empty, Hash, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader} }; @@ -54,13 +54,13 @@ impl Deserialize for Nullifier { } impl Readable for Nullifier { - fn assert_match_read_request(self, read_request: ReadRequestContext) { + fn assert_match_read_request(self, read_request: ScopedReadRequest) { // Public kernels output Nullifier instead of ScopedNullifier. // The nullifier value has been siloed. - let siloed_request_value = silo_nullifier(read_request.contract_address, read_request.value); + let siloed_request_value = silo_nullifier(read_request.contract_address, read_request.value()); assert_eq(self.value, siloed_request_value, "Value of the nullifier does not match read request"); assert( - read_request.counter > self.counter, "Read request counter must be greater than the counter of the nullifier" + read_request.counter() > self.counter, "Read request counter must be greater than the counter of the nullifier" ); } } @@ -126,11 +126,11 @@ impl Deserialize for ScopedNullifier { } impl Readable for ScopedNullifier { - fn assert_match_read_request(self, read_request: ReadRequestContext) { - assert_eq(self.nullifier.value, read_request.value, "Value of the nullifier does not match read request"); + fn assert_match_read_request(self, read_request: ScopedReadRequest) { + assert_eq(self.nullifier.value, read_request.value(), "Value of the nullifier does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the nullifier does not match read request"); assert( - read_request.counter > self.nullifier.counter, "Read request counter must be greater than the counter of the nullifier" + read_request.counter() > self.nullifier.counter, "Read request counter must be greater than the counter of the nullifier" ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr index 0dcba717633..2eaf66edc90 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -1,7 +1,7 @@ global NULLIFIER_LEAF_PREIMAGE_LENGTH: u64 = 3; use crate::{ - abis::{read_request::ReadRequestContext, side_effect::Readable}, hash::silo_nullifier, + abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::silo_nullifier, merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash} }; @@ -56,8 +56,8 @@ impl IndexedTreeLeafPreimage for NullifierLeafPreimage { } impl Readable for NullifierLeafPreimage { - fn assert_match_read_request(self, read_request: ReadRequestContext) { - let siloed_value = silo_nullifier(read_request.contract_address, read_request.value); + fn assert_match_read_request(self, read_request: ScopedReadRequest) { + let siloed_value = silo_nullifier(read_request.contract_address, read_request.value()); assert_eq(self.nullifier, siloed_value, "Value of the nullifier leaf does not match read request"); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr index f0129031bb3..5bea5734d80 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr @@ -1,7 +1,10 @@ -use crate::{traits::{Empty, Serialize, Deserialize}, address::AztecAddress, constants::READ_REQUEST_LENGTH}; +use crate::{ + traits::{Empty, Serialize, Deserialize}, address::AztecAddress, constants::READ_REQUEST_LENGTH, + utils::{arrays::array_concat, reader::Reader} +}; use dep::std::cmp::Eq; -global READ_REQUEST_CONTEXT_SERIALIZED_LEN = 3; +global SCOPED_READ_REQUEST_SERIALIZED_LEN = READ_REQUEST_LENGTH + 1; struct ReadRequest { value: Field, @@ -40,48 +43,55 @@ impl Deserialize for ReadRequest { } impl ReadRequest { - pub fn to_context(self, contract_address: AztecAddress) -> ReadRequestContext { - ReadRequestContext { value: self.value, counter: self.counter, contract_address } + pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest { + ScopedReadRequest { read_request: self, contract_address } } } -struct ReadRequestContext { - value: Field, - counter: u32, +struct ScopedReadRequest { + read_request: ReadRequest, contract_address: AztecAddress, } -impl Eq for ReadRequestContext { - fn eq(self, read_request: ReadRequestContext) -> bool { - (self.value == read_request.value) - & (self.counter == read_request.counter) - & (self.contract_address.eq(read_request.contract_address)) +impl Eq for ScopedReadRequest { + fn eq(self, other: ScopedReadRequest) -> bool { + (self.read_request == other.read_request) + & (self.contract_address.eq(other.contract_address)) } } -impl Empty for ReadRequestContext { +impl Empty for ScopedReadRequest { fn empty() -> Self { - ReadRequestContext { - value: 0, - counter: 0, + ScopedReadRequest { + read_request: ReadRequest::empty(), contract_address: AztecAddress::empty(), } } } -impl Serialize for ReadRequestContext { - fn serialize(self) -> [Field; READ_REQUEST_CONTEXT_SERIALIZED_LEN] { - [self.value, self.counter as Field, self.contract_address.to_field()] +impl Serialize for ScopedReadRequest { + fn serialize(self) -> [Field; SCOPED_READ_REQUEST_SERIALIZED_LEN] { + array_concat(self.read_request.serialize(), [self.contract_address.to_field()]) } } -impl Deserialize for ReadRequestContext { - fn deserialize(values: [Field; READ_REQUEST_CONTEXT_SERIALIZED_LEN]) -> Self { - Self { - value: values[0], - counter: values[1] as u32, +impl Deserialize for ScopedReadRequest { + fn deserialize(values: [Field; SCOPED_READ_REQUEST_SERIALIZED_LEN]) -> Self { + let mut reader = Reader::new(values); + let res = Self { + read_request: reader.read_struct(ReadRequest::deserialize), contract_address: AztecAddress::from_field(values[2]), - } + }; + reader.finish(); + res } } +impl ScopedReadRequest { + pub fn value(self) -> Field { + self.read_request.value + } + pub fn counter(self) -> u32 { + self.read_request.counter + } +} \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr index 2f1de297ac4..78b54a59a0b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr @@ -1,5 +1,5 @@ use crate::{ - abis::read_request::ReadRequestContext, address::AztecAddress, + abis::read_request::ScopedReadRequest, address::AztecAddress, constants::{GENERATOR_INDEX__SIDE_EFFECT, SIDE_EFFECT_LENGTH}, traits::{Empty, Hash, Serialize, Deserialize} }; @@ -15,7 +15,7 @@ trait OrderedValue where T: Eq { } trait Readable { - fn assert_match_read_request(self, read_request: ReadRequestContext); + fn assert_match_read_request(self, read_request: ScopedReadRequest); } struct SideEffect { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr index c49acd2e912..1ca8b39c9c6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequestContext, - public_data_read::PublicDataRead, read_request::ReadRequestContext, + public_data_read::PublicDataRead, read_request::ScopedReadRequest, validation_requests::rollup_validation_requests::RollupValidationRequests }, constants::{ @@ -15,9 +15,9 @@ use crate::{ // TODO - Use specific structs for private and public: PrivateValidationRequests vs PublicValidationRequests struct ValidationRequests { for_rollup: RollupValidationRequests, - note_hash_read_requests: [ReadRequestContext; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - nullifier_read_requests: [ReadRequestContext; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - nullifier_non_existent_read_requests: [ReadRequestContext; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], + note_hash_read_requests: [ScopedReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], nullifier_key_validation_requests: [NullifierKeyValidationRequestContext; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr index 7aa661a9def..91c0ad299de 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequestContext, - public_data_read::PublicDataRead, read_request::ReadRequestContext, + public_data_read::PublicDataRead, read_request::ScopedReadRequest, validation_requests::validation_requests::ValidationRequests, validation_requests::rollup_validation_requests::RollupValidationRequests }, @@ -16,9 +16,9 @@ use crate::{ struct ValidationRequestsBuilder { max_block_number: MaxBlockNumber, - note_hash_read_requests: BoundedVec, - nullifier_read_requests: BoundedVec, - nullifier_non_existent_read_requests: BoundedVec, + note_hash_read_requests: BoundedVec, + nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, nullifier_key_validation_requests: BoundedVec, public_data_reads: BoundedVec, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 4a70575949d..a2843a3b87d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -9,7 +9,7 @@ use crate::{ note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - read_request::ReadRequestContext, side_effect::SideEffect, + read_request::{ReadRequest, ScopedReadRequest}, side_effect::SideEffect, validation_requests::{ValidationRequests, ValidationRequestsBuilder} }, address::{AztecAddress, EthAddress}, @@ -55,9 +55,9 @@ struct FixtureBuilder { // Validation requests. max_block_number: MaxBlockNumber, - note_hash_read_requests: BoundedVec, - nullifier_read_requests: BoundedVec, - nullifier_non_existent_read_requests: BoundedVec, + note_hash_read_requests: BoundedVec, + nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, nullifier_key_validation_requests: BoundedVec, public_data_reads: BoundedVec, @@ -341,7 +341,7 @@ impl FixtureBuilder { pub fn add_read_request_for_pending_note_hash(&mut self, note_hash_index: u64) -> u64 { let read_request_index = self.note_hash_read_requests.len(); let value = self.get_mocked_note_hash_value(note_hash_index); - let read_request = ReadRequestContext { value, counter: self.next_counter(), contract_address: self.storage_contract_address }; + let read_request = ReadRequest { value, counter: self.next_counter() }.scope(self.storage_contract_address); self.note_hash_read_requests.push(read_request); read_request_index } @@ -350,11 +350,7 @@ impl FixtureBuilder { let value_offset = self.note_hash_read_requests.len(); for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_TX { if i < num_reads { - let read_request = ReadRequestContext { - value: (value_offset + i + 789) as Field, - counter: self.next_counter(), - contract_address: self.storage_contract_address - }; + let read_request = ReadRequest { value: (value_offset + i + 789) as Field, counter: self.next_counter() }.scope(self.storage_contract_address); self.note_hash_read_requests.push(read_request); } } @@ -363,13 +359,13 @@ impl FixtureBuilder { pub fn add_read_request_for_pending_nullifier(&mut self, nullifier_index: u64) -> u64 { let read_request_index = self.nullifier_read_requests.len(); let nullifier = self.get_mocked_nullifier_value(nullifier_index); - let read_request = ReadRequestContext { value: nullifier, counter: self.next_counter(), contract_address: self.storage_contract_address }; + let read_request = ReadRequest { value: nullifier, counter: self.next_counter() }.scope(self.storage_contract_address); self.nullifier_read_requests.push(read_request); read_request_index } pub fn add_non_existent_read_request_for_nullifier(&mut self, nullifier: Field) { - let read_request = ReadRequestContext { value: nullifier, counter: self.next_counter(), contract_address: self.storage_contract_address }; + let read_request = ReadRequest { value: nullifier, counter: self.next_counter() }.scope(self.storage_contract_address); self.nullifier_non_existent_read_requests.push(read_request); } 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 1aa3b1f0880..fa15e1b15ed 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 @@ -10,9 +10,10 @@ import { type NoteHashReadRequestHints, NoteHashReadRequestHintsBuilder, PendingReadHint, - ReadRequestContext, + ReadRequest, ReadRequestStatus, type ScopedNoteHash, + ScopedReadRequest, SettledReadHint, } from '../structs/index.js'; import { buildNoteHashReadRequestHints } from './build_note_hash_read_request_hints.js'; @@ -26,7 +27,7 @@ describe('buildNoteHashReadRequestHints', () => { getNoteHashMembershipWitness: (leafIndex: bigint) => settledLeafIndexes.includes(leafIndex) ? ({} as any) : undefined, }; - let noteHashReadRequests: Tuple; + let noteHashReadRequests: Tuple; let noteHashes: Tuple; let noteHashLeafIndexMap: Map = new Map(); let expectedHints: NoteHashReadRequestHints; @@ -37,7 +38,7 @@ describe('buildNoteHashReadRequestHints', () => { const innerNoteHash = (index: number) => index + 9999; const makeReadRequest = (value: number, counter = 2) => - new ReadRequestContext(new Fr(value), counter, contractAddress); + new ReadRequest(new Fr(value), counter).scope(contractAddress); const makeNoteHash = (value: number, counter = 1) => new NoteHash(new Fr(value), counter).scope(0, contractAddress); @@ -66,7 +67,7 @@ describe('buildNoteHashReadRequestHints', () => { } = {}) => { const value = settledNoteHashes[hintIndex]; noteHashLeafIndexMap.set(value.toBigInt(), settledLeafIndexes[hintIndex]); - noteHashReadRequests[readRequestIndex] = new ReadRequestContext(value, 1, contractAddress); + noteHashReadRequests[readRequestIndex] = new ReadRequest(value, 1).scope(contractAddress); expectedHints.readRequestStatuses[readRequestIndex] = ReadRequestStatus.settled(hintIndex); expectedHints.settledReadHints[hintIndex] = new SettledReadHint(readRequestIndex, {} as any, value); numReadRequests++; @@ -77,7 +78,7 @@ describe('buildNoteHashReadRequestHints', () => { buildNoteHashReadRequestHints(oracle, noteHashReadRequests, noteHashes, noteHashLeafIndexMap); beforeEach(() => { - noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ReadRequestContext.empty); + 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(); @@ -119,7 +120,7 @@ describe('buildNoteHashReadRequestHints', () => { it('throws if cannot find a match in pending set and in the tree', async () => { readPendingNoteHash({ noteHashIndex: 2 }); // Tweak the value of the read request. - noteHashReadRequests[0].value = new Fr(123); + noteHashReadRequests[0].readRequest.value = new Fr(123); await expect(() => buildHints()).rejects.toThrow('Read request is reading an unknown note hash.'); }); }); 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 2e21c66d978..4fc62f76216 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 @@ -8,12 +8,12 @@ import { import { type MembershipWitness, NoteHashReadRequestHintsBuilder, - type ReadRequestContext, type ScopedNoteHash, + type ScopedReadRequest, } from '../structs/index.js'; import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; -function isValidNoteHashReadRequest(readRequest: ReadRequestContext, noteHash: ScopedNoteHash) { +function isValidNoteHashReadRequest(readRequest: ScopedReadRequest, noteHash: ScopedNoteHash) { return ( noteHash.contractAddress.equals(readRequest.contractAddress) && readRequest.counter > noteHash.counter && @@ -25,7 +25,7 @@ export async function buildNoteHashReadRequestHints( oracle: { getNoteHashMembershipWitness(leafIndex: bigint): Promise>; }, - noteHashReadRequests: Tuple, + noteHashReadRequests: Tuple, noteHashes: Tuple, noteHashLeafIndexMap: Map, ) { diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts index 7d4040e35c8..89a2fb7ed6d 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts @@ -5,7 +5,12 @@ import { Fr } from '@aztec/foundation/fields'; import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { siloNullifier } from '../hash/index.js'; -import { Nullifier, NullifierNonExistentReadRequestHintsBuilder, ReadRequestContext } from '../structs/index.js'; +import { + Nullifier, + NullifierNonExistentReadRequestHintsBuilder, + ReadRequest, + ScopedReadRequest, +} from '../structs/index.js'; import { buildNullifierNonExistentReadRequestHints } from './build_nullifier_non_existent_read_request_hints.js'; describe('buildNullifierNonExistentReadRequestHints', () => { @@ -13,13 +18,13 @@ describe('buildNullifierNonExistentReadRequestHints', () => { const oracle = { getLowNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; - const nonExistentReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty); + const nonExistentReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); let nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty); const innerNullifier = (index: number) => index + 1; const makeReadRequest = (value: number, counter = 2) => - new ReadRequestContext(new Fr(value), counter, contractAddress); + new ReadRequest(new Fr(value), counter).scope(contractAddress); const makeNullifier = (value: number, counter = 1) => { const siloedValue = siloNullifier(contractAddress, new Fr(value)); diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts index c2f65701402..5bb6fa3eb76 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts @@ -12,7 +12,7 @@ import { siloNullifier } from '../hash/index.js'; import { Nullifier } from '../structs/index.js'; import { type MembershipWitness } from '../structs/membership_witness.js'; import { NullifierNonExistentReadRequestHintsBuilder } from '../structs/non_existent_read_request_hints.js'; -import { type ReadRequestContext } from '../structs/read_request.js'; +import { type ScopedReadRequest } from '../structs/read_request.js'; import { countAccumulatedItems } from '../utils/index.js'; interface NullifierMembershipWitnessWithPreimage { @@ -53,7 +53,7 @@ export async function buildNullifierNonExistentReadRequestHints( oracle: { getLowNullifierMembershipWitness(nullifier: Fr): Promise; }, - nullifierNonExistentReadRequests: Tuple, + nullifierNonExistentReadRequests: Tuple, pendingNullifiers: Tuple, ) { const { sortedValues, sortedIndexHints } = sortNullifiersByValues(pendingNullifiers); 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 332113a435c..bec3d9d5a8b 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 @@ -9,10 +9,11 @@ import { type NullifierReadRequestHints, NullifierReadRequestHintsBuilder, PendingReadHint, - ReadRequestContext, + ReadRequest, ReadRequestState, ReadRequestStatus, type ScopedNullifier, + ScopedReadRequest, SettledReadHint, } from '../structs/index.js'; import { buildNullifierReadRequestHints } from './build_nullifier_read_request_hints.js'; @@ -23,7 +24,7 @@ describe('buildNullifierReadRequestHints', () => { const oracle = { getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; - let nullifierReadRequests: Tuple; + let nullifierReadRequests: Tuple; let nullifiers: Tuple; let expectedHints: NullifierReadRequestHints; let numReadRequests = 0; @@ -33,7 +34,7 @@ describe('buildNullifierReadRequestHints', () => { const innerNullifier = (index: number) => index + 1; const makeReadRequest = (value: number, counter = 2) => - new ReadRequestContext(new Fr(value), counter, contractAddress); + new ReadRequest(new Fr(value), counter).scope(contractAddress); const makeNullifier = (value: number, counter = 1) => new Nullifier(new Fr(value), counter, Fr.ZERO).scope(contractAddress); @@ -71,7 +72,7 @@ describe('buildNullifierReadRequestHints', () => { const buildHints = () => buildNullifierReadRequestHints(oracle, nullifierReadRequests, nullifiers); beforeEach(() => { - nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty); + nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); expectedHints = NullifierReadRequestHintsBuilder.empty(); numReadRequests = 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 9615ebd7f03..9a1cbb38ae8 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 @@ -14,8 +14,9 @@ import { type MembershipWitness, Nullifier, NullifierReadRequestHintsBuilder, - ReadRequestContext, + ReadRequest, type ScopedNullifier, + ScopedReadRequest, } from '../structs/index.js'; import { countAccumulatedItems, getNonEmptyItems } from '../utils/index.js'; @@ -28,7 +29,7 @@ export async function buildNullifierReadRequestHints( oracle: { getNullifierMembershipWitness(nullifier: Fr): Promise; }, - nullifierReadRequests: Tuple, + nullifierReadRequests: Tuple, nullifiers: Tuple, siloed = false, ) { @@ -72,16 +73,16 @@ export function buildSiloedNullifierReadRequestHints( oracle: { getNullifierMembershipWitness(nullifier: Fr): Promise; }, - nullifierReadRequests: Tuple, + nullifierReadRequests: Tuple, nullifiers: Tuple, ) { // 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. const siloedReadRequests = padArrayEnd( - getNonEmptyItems(nullifierReadRequests).map( - r => new ReadRequestContext(siloNullifier(r.contractAddress, r.value), r.counter, AztecAddress.ZERO), + getNonEmptyItems(nullifierReadRequests).map(r => + new ReadRequest(siloNullifier(r.contractAddress, r.value), r.counter).scope(AztecAddress.ZERO), ), - ReadRequestContext.empty(), + ScopedReadRequest.empty(), MAX_NULLIFIER_READ_REQUESTS_PER_TX, ); diff --git a/yarn-project/circuits.js/src/structs/read_request.ts b/yarn-project/circuits.js/src/structs/read_request.ts index 1f47f967c6d..60127af7c0d 100644 --- a/yarn-project/circuits.js/src/structs/read_request.ts +++ b/yarn-project/circuits.js/src/structs/read_request.ts @@ -60,43 +60,42 @@ export class ReadRequest { static empty(): ReadRequest { return new ReadRequest(Fr.zero(), 0); } + + scope(contractAddress: AztecAddress) { + return new ScopedReadRequest(this, contractAddress); + } } /** * ReadRequest with context of the contract emitting the request. */ -export class ReadRequestContext { - constructor( - /** - * The value being read. - */ - public value: Fr, - /** - * The counter. - */ - public counter: number, - /** - * The address of the contract emitting the request. - */ - public contractAddress: AztecAddress, - ) {} +export class ScopedReadRequest { + constructor(public readRequest: ReadRequest, public contractAddress: AztecAddress) {} + + get value() { + return this.readRequest.value; + } + + get counter() { + return this.readRequest.counter; + } /** * Serialize this as a buffer. * @returns The buffer. */ toBuffer(): Buffer { - return serializeToBuffer(this.value, this.counter, this.contractAddress); + return serializeToBuffer(this.readRequest, this.contractAddress); } /** * Deserializes from a buffer or reader, corresponding to a write in cpp. * @param buffer - Buffer or reader to read from. - * @returns A new instance of ReadRequestContext. + * @returns A new instance of ScopedReadRequest. */ static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new ReadRequestContext(Fr.fromBuffer(reader), reader.readNumber(), AztecAddress.fromBuffer(reader)); + return new ScopedReadRequest(ReadRequest.fromBuffer(reader), AztecAddress.fromBuffer(reader)); } /** @@ -104,12 +103,12 @@ export class ReadRequestContext { * @returns The array of fields. */ toFields(): Fr[] { - return [this.value, new Fr(this.counter), this.contractAddress.toField()]; + return [...this.readRequest.toFields(), this.contractAddress.toField()]; } static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new ReadRequestContext(reader.readField(), reader.readU32(), AztecAddress.fromField(reader.readField())); + return new ScopedReadRequest(reader.readObject(ReadRequest), AztecAddress.fromField(reader.readField())); } /** @@ -117,14 +116,14 @@ export class ReadRequestContext { * @returns True if the value, note hash and counter are all zero. */ isEmpty() { - return this.value.isZero() && !this.counter && this.contractAddress.isZero(); + return this.readRequest.isEmpty() && this.contractAddress.isZero(); } /** * Returns an empty instance of side-effect. * @returns Side-effect with value, note hash and counter being zero. */ - static empty(): ReadRequestContext { - return new ReadRequestContext(Fr.zero(), 0, AztecAddress.ZERO); + static empty(): ScopedReadRequest { + return new ScopedReadRequest(ReadRequest.empty(), AztecAddress.ZERO); } } diff --git a/yarn-project/circuits.js/src/structs/validation_requests.ts b/yarn-project/circuits.js/src/structs/validation_requests.ts index 839c08e7815..ad386e2180c 100644 --- a/yarn-project/circuits.js/src/structs/validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/validation_requests.ts @@ -12,7 +12,7 @@ import { } from '../constants.gen.js'; import { NullifierKeyValidationRequestContext } from './nullifier_key_validation_request.js'; import { PublicDataRead } from './public_data_read_request.js'; -import { ReadRequestContext } from './read_request.js'; +import { ScopedReadRequest } from './read_request.js'; import { RollupValidationRequests } from './rollup_validation_requests.js'; /** @@ -28,16 +28,16 @@ export class ValidationRequests { /** * All the read requests made in this transaction. */ - public noteHashReadRequests: Tuple, + public noteHashReadRequests: Tuple, /** * All the nullifier read requests made in this transaction. */ - public nullifierReadRequests: Tuple, + public nullifierReadRequests: Tuple, /** * The nullifier read requests made in this transaction. */ public nullifierNonExistentReadRequests: Tuple< - ReadRequestContext, + ScopedReadRequest, typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX >, /** @@ -77,9 +77,9 @@ export class ValidationRequests { const reader = BufferReader.asReader(buffer); return new ValidationRequests( reader.readObject(RollupValidationRequests), - reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ReadRequestContext), - reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext), - reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ReadRequestContext), + reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, NullifierKeyValidationRequestContext), reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), ); @@ -97,9 +97,9 @@ export class ValidationRequests { static empty() { return new ValidationRequests( RollupValidationRequests.empty(), - makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ReadRequestContext.empty), - makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty), - makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ReadRequestContext.empty), + makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), + makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, NullifierKeyValidationRequestContext.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), ); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 6b3fae0ce6f..3aa68b63244 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -111,13 +111,13 @@ import { RECURSIVE_PROOF_LENGTH, ROLLUP_VK_TREE_HEIGHT, ReadRequest, - ReadRequestContext, RevertCode, RollupTypes, RootParityInput, RootParityInputs, RootRollupInputs, RootRollupPublicInputs, + ScopedReadRequest, SideEffect, StateDiffHints, StateReference, @@ -198,8 +198,8 @@ function makeReadRequest(n: number): ReadRequest { return new ReadRequest(new Fr(BigInt(n)), n + 1); } -function makeReadRequestContext(n: number): ReadRequestContext { - return new ReadRequestContext(new Fr(BigInt(n)), n + 1, AztecAddress.fromBigInt(BigInt(n + 2))); +function makeScopedReadRequest(n: number): ScopedReadRequest { + return new ScopedReadRequest(makeReadRequest(n), AztecAddress.fromBigInt(BigInt(n + 2))); } /** @@ -275,9 +275,9 @@ export function makeContractStorageRead(seed = 1): ContractStorageRead { export function makeValidationRequests(seed = 1) { return new ValidationRequests( makeRollupValidationRequests(seed), - makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, makeReadRequestContext, seed + 0x80), - makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, makeReadRequestContext, seed + 0x90), - makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, makeReadRequestContext, seed + 0x95), + makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x80), + makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x90), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x95), makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, makeNullifierKeyValidationRequestContext, seed + 0x100), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, makePublicDataRead, seed + 0xe00), ); 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 463b31940e0..50f0c918a9d 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -97,7 +97,6 @@ import { type PublicKernelTailCircuitPrivateInputs, type RECURSIVE_PROOF_LENGTH, ReadRequest, - ReadRequestContext, type ReadRequestStatus, type RecursiveProof, RevertCode, @@ -109,6 +108,7 @@ import { ScopedL2ToL1Message, ScopedNoteHash, ScopedNullifier, + ScopedReadRequest, type SettledReadHint, SideEffect, type StateDiffHints, @@ -153,12 +153,12 @@ import { type PrivateKernelCircuitPublicInputs as PrivateKernelCircuitPublicInputsNoir, type PrivateKernelInitCircuitPrivateInputs as PrivateKernelInitCircuitPrivateInputsNoir, type PublicDataRead as PublicDataReadNoir, - type ReadRequestContext as ReadRequestContextNoir, type ReadRequest as ReadRequestNoir, type RollupValidationRequests as RollupValidationRequestsNoir, type ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, type ScopedNoteHash as ScopedNoteHashNoir, type ScopedNullifier as ScopedNullifierNoir, + type ScopedReadRequest as ScopedReadRequestNoir, type SideEffect as SideEffectNoir, type TxContext as TxContextNoir, type TxRequest as TxRequestNoir, @@ -647,16 +647,10 @@ export function mapReadRequestFromNoir(readRequest: ReadRequestNoir): ReadReques return new ReadRequest(mapFieldFromNoir(readRequest.value), mapNumberFromNoir(readRequest.counter)); } -/** - * Maps a ReadRequestContext to a noir ReadRequestContext. - * @param readRequestContext - The read request context. - * @returns The noir ReadRequestContext. - */ -export function mapReadRequestContextToNoir(readRequestContext: ReadRequestContext): ReadRequestContextNoir { +function mapScopedReadRequestToNoir(scopedReadRequest: ScopedReadRequest): ScopedReadRequestNoir { return { - value: mapFieldToNoir(readRequestContext.value), - counter: mapNumberToNoir(readRequestContext.counter), - contract_address: mapAztecAddressToNoir(readRequestContext.contractAddress), + read_request: mapReadRequestToNoir(scopedReadRequest.readRequest), + contract_address: mapAztecAddressToNoir(scopedReadRequest.contractAddress), }; } @@ -665,11 +659,10 @@ export function mapReadRequestContextToNoir(readRequestContext: ReadRequestConte * @param readRequest - The noir ReadRequest. * @returns The TS ReadRequest. */ -export function mapReadRequestContextFromNoir(readRequestContext: ReadRequestContextNoir): ReadRequestContext { - return new ReadRequestContext( - mapFieldFromNoir(readRequestContext.value), - mapNumberFromNoir(readRequestContext.counter), - mapAztecAddressFromNoir(readRequestContext.contract_address), +export function mapScopedReadRequestFromNoir(scoped: ScopedReadRequestNoir): ScopedReadRequest { + return new ScopedReadRequest( + mapReadRequestFromNoir(scoped.read_request), + mapAztecAddressFromNoir(scoped.contract_address), ); } @@ -1044,11 +1037,11 @@ function mapPublicDataReadRequestHintsToNoir(hints: PublicDataReadRequestHints): function mapValidationRequestsToNoir(requests: ValidationRequests): ValidationRequestsNoir { return { for_rollup: mapRollupValidationRequestsToNoir(requests.forRollup), - note_hash_read_requests: mapTuple(requests.noteHashReadRequests, mapReadRequestContextToNoir), - nullifier_read_requests: mapTuple(requests.nullifierReadRequests, mapReadRequestContextToNoir), + note_hash_read_requests: mapTuple(requests.noteHashReadRequests, mapScopedReadRequestToNoir), + nullifier_read_requests: mapTuple(requests.nullifierReadRequests, mapScopedReadRequestToNoir), nullifier_non_existent_read_requests: mapTuple( requests.nullifierNonExistentReadRequests, - mapReadRequestContextToNoir, + mapScopedReadRequestToNoir, ), nullifier_key_validation_requests: mapTuple( requests.nullifierKeyValidationRequests, @@ -1064,17 +1057,17 @@ function mapValidationRequestsFromNoir(requests: ValidationRequestsNoir): Valida mapTupleFromNoir( requests.note_hash_read_requests, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - mapReadRequestContextFromNoir, + mapScopedReadRequestFromNoir, ), mapTupleFromNoir( requests.nullifier_read_requests, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - mapReadRequestContextFromNoir, + mapScopedReadRequestFromNoir, ), mapTupleFromNoir( requests.nullifier_non_existent_read_requests, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - mapReadRequestContextFromNoir, + mapScopedReadRequestFromNoir, ), mapTupleFromNoir( requests.nullifier_key_validation_requests, diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index 1346349ae40..c859d3bde83 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -12,8 +12,8 @@ import { type NullifierKeyValidationRequestContext, type PrivateKernelCircuitPublicInputs, PrivateKernelTailHints, - type ReadRequestContext, type ScopedNullifier, + type ScopedReadRequest, type SideEffect, type SideEffectType, buildNoteHashReadRequestHints, @@ -49,7 +49,7 @@ function sortSideEffects( } function getNullifierReadRequestHints( - nullifierReadRequests: Tuple, + nullifierReadRequests: Tuple, nullifiers: Tuple, oracle: ProvingDataOracle, ) { diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index f88af9b87b0..0d83cd44db4 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -15,7 +15,7 @@ import { type PublicDataRead, type PublicDataTreeLeafPreimage, type PublicDataUpdateRequest, - type ReadRequestContext, + type ScopedReadRequest, buildNullifierNonExistentReadRequestHints, buildPublicDataHints, buildPublicDataReadRequestHints, @@ -28,14 +28,14 @@ export class HintsBuilder { constructor(private db: MerkleTreeOperations) {} getNullifierReadRequestHints( - nullifierReadRequests: Tuple, + nullifierReadRequests: Tuple, pendingNullifiers: Tuple, ) { return buildSiloedNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers); } getNullifierNonExistentReadRequestHints( - nullifierNonExistentReadRequests: Tuple, + nullifierNonExistentReadRequests: Tuple, pendingNullifiers: Tuple, ) { return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers); From e181faed939d4042a3dda33c4babed5aa70dae4f Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Wed, 8 May 2024 00:15:33 +0000 Subject: [PATCH 11/13] Rename NullifierKeyValidationRequestContext to ScopedNullifierKeyValidationRequest. --- ...e_kernel_circuit_public_inputs_composer.nr | 2 +- .../src/private_kernel_init.nr | 11 ++-- .../private_validation_request_processor.nr | 5 +- .../abis/nullifier_key_validation_request.nr | 58 ++++++++----------- .../validation_requests.nr | 4 +- .../validation_requests_builder.nr | 4 +- .../crates/types/src/constants.nr | 2 +- .../crates/types/src/tests/fixture_builder.nr | 4 +- .../nullifier_key_validation_request.ts | 41 ++++--------- .../src/structs/validation_requests.ts | 8 +-- .../circuits.js/src/tests/factories.ts | 13 ++--- .../src/type_conversion.ts | 38 +++++------- .../build_private_kernel_tail_hints.ts | 4 +- 13 files changed, 75 insertions(+), 119 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index 6efd4d56c8e..dda3224b07d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -137,7 +137,7 @@ impl PrivateKernelCircuitPublicInputsComposer { for i in 0..nullifier_key_validation_requests.len() { let request = nullifier_key_validation_requests[i]; if !is_empty(request) { - self.public_inputs.validation_requests.nullifier_key_validation_requests.push(request.to_context(source.storage_contract_address)); + self.public_inputs.validation_requests.nullifier_key_validation_requests.push(request.scope(source.storage_contract_address)); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index cb5aca1f969..64a08cdc7b1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -405,18 +405,17 @@ mod tests { fn propagate_nullifier_key_validation_requests() { let mut builder = PrivateKernelInitInputsBuilder::new(); - let request = NullifierKeyValidationRequest { master_nullifier_public_key: GrumpkinPoint { x: 1, y: 2 }, app_nullifier_secret_key: 3 }; - builder.private_call.public_inputs.nullifier_key_validation_requests.push(request); + let request_0 = NullifierKeyValidationRequest { master_nullifier_public_key: GrumpkinPoint { x: 1, y: 2 }, app_nullifier_secret_key: 3 }; + builder.private_call.public_inputs.nullifier_key_validation_requests.push(request_0); let public_inputs = builder.execute(); assert_eq(array_length(public_inputs.validation_requests.nullifier_key_validation_requests), 1); - let request_context = public_inputs.validation_requests.nullifier_key_validation_requests[0]; - assert_eq(request_context.master_nullifier_public_key, request.master_nullifier_public_key); - assert_eq(request_context.app_nullifier_secret_key, request.app_nullifier_secret_key); + let request = public_inputs.validation_requests.nullifier_key_validation_requests[0]; + assert_eq(request.request, request_0); assert_eq( - request_context.contract_address, builder.private_call.public_inputs.call_context.storage_contract_address + request.contract_address, builder.private_call.public_inputs.call_context.storage_contract_address ); } } 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 9dd186a0484..08d63cb14d8 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 @@ -62,8 +62,9 @@ impl PrivateValidationRequestProcessor { fn validate_nullifier_keys(self) { let requests = self.validation_requests.nullifier_key_validation_requests; for i in 0..MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX { - let request = requests[i]; + 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]; // 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(); @@ -75,7 +76,7 @@ impl PrivateValidationRequestProcessor { let app_nullifier_secret_key = poseidon2_hash( [ - master_nullifier_secret_key.high, master_nullifier_secret_key.low, request.contract_address.to_field(), GENERATOR_INDEX__NSK_M + master_nullifier_secret_key.high, master_nullifier_secret_key.low, contract_address.to_field(), GENERATOR_INDEX__NSK_M ] ); assert( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr index 1a08e9f7a2f..351df627b2a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr @@ -1,9 +1,9 @@ use dep::std::cmp::Eq; use crate::{ address::AztecAddress, - constants::{NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH, NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH}, + constants::{NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH, SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH}, traits::{Empty, Serialize, Deserialize}, grumpkin_point::GrumpkinPoint, - grumpkin_private_key::GrumpkinPrivateKey + grumpkin_private_key::GrumpkinPrivateKey, utils::{arrays::array_concat, reader::Reader} }; struct NullifierKeyValidationRequest { @@ -47,57 +47,47 @@ impl Deserialize for NullifierKeyValida } impl NullifierKeyValidationRequest { - pub fn to_context(self, contract_address: AztecAddress) -> NullifierKeyValidationRequestContext { - NullifierKeyValidationRequestContext { - master_nullifier_public_key: self.master_nullifier_public_key, - app_nullifier_secret_key: self.app_nullifier_secret_key, - contract_address - } + pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifierKeyValidationRequest { + ScopedNullifierKeyValidationRequest { request: self, contract_address } } } -struct NullifierKeyValidationRequestContext { - master_nullifier_public_key: GrumpkinPoint, - app_nullifier_secret_key: Field, +struct ScopedNullifierKeyValidationRequest { + request: NullifierKeyValidationRequest, contract_address: AztecAddress, } -impl Eq for NullifierKeyValidationRequestContext { - fn eq(self, request: NullifierKeyValidationRequestContext) -> bool { - (request.master_nullifier_public_key.eq(self.master_nullifier_public_key)) - & (request.app_nullifier_secret_key.eq(self.app_nullifier_secret_key)) - & (request.contract_address.eq(self.contract_address)) +impl Eq for ScopedNullifierKeyValidationRequest { + fn eq(self, other: ScopedNullifierKeyValidationRequest) -> bool { + (self.request.eq(other.request)) + & (self.contract_address.eq(other.contract_address)) } } -impl Empty for NullifierKeyValidationRequestContext { +impl Empty for ScopedNullifierKeyValidationRequest { fn empty() -> Self { - NullifierKeyValidationRequestContext { - master_nullifier_public_key: GrumpkinPoint::zero(), - app_nullifier_secret_key: 0, + ScopedNullifierKeyValidationRequest { + request: NullifierKeyValidationRequest::empty(), contract_address: AztecAddress::zero(), } } } -impl Serialize for NullifierKeyValidationRequestContext { - fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH] { - [ - self.master_nullifier_public_key.x, - self.master_nullifier_public_key.y, - self.app_nullifier_secret_key, - self.contract_address.to_field(), - ] +impl Serialize for ScopedNullifierKeyValidationRequest { + fn serialize(self) -> [Field; SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH] { + array_concat(self.request.serialize(), [self.contract_address.to_field()]) } } -impl Deserialize for NullifierKeyValidationRequestContext { - fn deserialize(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH]) -> Self { - Self { - master_nullifier_public_key: GrumpkinPoint::new(fields[0], fields[1]), - app_nullifier_secret_key: fields[2], +impl Deserialize for ScopedNullifierKeyValidationRequest { + fn deserialize(fields: [Field; SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH]) -> Self { + let mut reader = Reader::new(fields); + let res = Self { + request: reader.read_struct(NullifierKeyValidationRequest::deserialize), contract_address: AztecAddress::from_field(fields[3]), - } + }; + reader.finish(); + res } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr index 1ca8b39c9c6..850afddbade 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ max_block_number::MaxBlockNumber, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + nullifier_key_validation_request::ScopedNullifierKeyValidationRequest, public_data_read::PublicDataRead, read_request::ScopedReadRequest, validation_requests::rollup_validation_requests::RollupValidationRequests }, @@ -18,6 +18,6 @@ struct ValidationRequests { note_hash_read_requests: [ScopedReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], - nullifier_key_validation_requests: [NullifierKeyValidationRequestContext; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], + nullifier_key_validation_requests: [ScopedNullifierKeyValidationRequest; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr index 91c0ad299de..6fe9d71310a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ max_block_number::MaxBlockNumber, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + nullifier_key_validation_request::ScopedNullifierKeyValidationRequest, public_data_read::PublicDataRead, read_request::ScopedReadRequest, validation_requests::validation_requests::ValidationRequests, validation_requests::rollup_validation_requests::RollupValidationRequests @@ -19,7 +19,7 @@ struct ValidationRequestsBuilder { note_hash_read_requests: BoundedVec, nullifier_read_requests: BoundedVec, nullifier_non_existent_read_requests: BoundedVec, - nullifier_key_validation_requests: BoundedVec, + nullifier_key_validation_requests: BoundedVec, public_data_reads: BoundedVec, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index edf929e239b..75aefa2c77d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -159,7 +159,7 @@ global L2_TO_L1_MESSAGE_LENGTH: u64 = 3; global SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the value global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; -global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; +global SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; global READ_REQUEST_LENGTH = 2; global NOTE_HASH_LENGTH = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index a2843a3b87d..077007c2b5a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -7,7 +7,7 @@ use crate::{ kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, kernel_data::{PrivateKernelData, PublicKernelData, KernelData}, max_block_number::MaxBlockNumber, note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + nullifier_key_validation_request::ScopedNullifierKeyValidationRequest, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::{ReadRequest, ScopedReadRequest}, side_effect::SideEffect, validation_requests::{ValidationRequests, ValidationRequestsBuilder} @@ -58,7 +58,7 @@ struct FixtureBuilder { note_hash_read_requests: BoundedVec, nullifier_read_requests: BoundedVec, nullifier_non_existent_read_requests: BoundedVec, - nullifier_key_validation_requests: BoundedVec, + nullifier_key_validation_requests: BoundedVec, public_data_reads: BoundedVec, // Proof. diff --git a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts index c145e0d2e82..b371142fbf8 100644 --- a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts +++ b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts @@ -58,61 +58,44 @@ export class NullifierKeyValidationRequest { /** * Request for validating a nullifier key pair used in the app. */ -export class NullifierKeyValidationRequestContext { - constructor( - /** - * Public key of the nullifier key (Npk_m). - */ - public readonly masterNullifierPublicKey: Point, - /** - * App-siloed nullifier secret key (nsk_app*). - */ - public readonly appNullifierSecretKey: Fr, - /** - * The storage contract address the nullifier key is for. - */ - public readonly contractAddress: AztecAddress, - ) {} +export class ScopedNullifierKeyValidationRequest { + constructor(public readonly request: NullifierKeyValidationRequest, public readonly contractAddress: AztecAddress) {} toBuffer() { - return serializeToBuffer(this.masterNullifierPublicKey, this.appNullifierSecretKey, this.contractAddress); + return serializeToBuffer(this.request, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new NullifierKeyValidationRequestContext( - Point.fromBuffer(reader), - Fr.fromBuffer(reader), + return new ScopedNullifierKeyValidationRequest( + NullifierKeyValidationRequest.fromBuffer(reader), AztecAddress.fromBuffer(reader), ); } toFields(): Fr[] { - const fields = [this.masterNullifierPublicKey.toFields(), this.appNullifierSecretKey, this.contractAddress].flat(); + const fields = [...this.request.toFields(), this.contractAddress].flat(); if (fields.length !== NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH) { throw new Error( - `Invalid number of fields for NullifierKeyValidationRequestContext. Expected ${NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH}, got ${fields.length}`, + `Invalid number of fields for ScopedNullifierKeyValidationRequest. Expected ${NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH}, got ${fields.length}`, ); } return fields; } - static fromFields(fields: Fr[] | FieldReader): NullifierKeyValidationRequestContext { + static fromFields(fields: Fr[] | FieldReader): ScopedNullifierKeyValidationRequest { const reader = FieldReader.asReader(fields); - return new NullifierKeyValidationRequestContext( - Point.fromFields(reader), - reader.readField(), + return new ScopedNullifierKeyValidationRequest( + NullifierKeyValidationRequest.fromFields(reader), AztecAddress.fromFields(reader), ); } isEmpty() { - return ( - this.masterNullifierPublicKey.isZero() && this.appNullifierSecretKey.isZero() && this.contractAddress.isZero() - ); + return this.request.isEmpty() && this.contractAddress.isZero(); } static empty() { - return new NullifierKeyValidationRequestContext(Point.ZERO, Fr.ZERO, AztecAddress.ZERO); + return new ScopedNullifierKeyValidationRequest(NullifierKeyValidationRequest.empty(), AztecAddress.ZERO); } } diff --git a/yarn-project/circuits.js/src/structs/validation_requests.ts b/yarn-project/circuits.js/src/structs/validation_requests.ts index ad386e2180c..6d33a5b5865 100644 --- a/yarn-project/circuits.js/src/structs/validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/validation_requests.ts @@ -10,7 +10,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, } from '../constants.gen.js'; -import { NullifierKeyValidationRequestContext } from './nullifier_key_validation_request.js'; +import { ScopedNullifierKeyValidationRequest } from './nullifier_key_validation_request.js'; import { PublicDataRead } from './public_data_read_request.js'; import { ScopedReadRequest } from './read_request.js'; import { RollupValidationRequests } from './rollup_validation_requests.js'; @@ -44,7 +44,7 @@ export class ValidationRequests { * All the nullifier key validation requests made in this transaction. */ public nullifierKeyValidationRequests: Tuple< - NullifierKeyValidationRequestContext, + ScopedNullifierKeyValidationRequest, typeof MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX >, /** @@ -80,7 +80,7 @@ export class ValidationRequests { reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), - reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, NullifierKeyValidationRequestContext), + reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, ScopedNullifierKeyValidationRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), ); } @@ -100,7 +100,7 @@ export class ValidationRequests { makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), - makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, NullifierKeyValidationRequestContext.empty), + makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, ScopedNullifierKeyValidationRequest.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 3aa68b63244..6dc5712a2fa 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -76,7 +76,6 @@ import { NoteHash, Nullifier, NullifierKeyValidationRequest, - NullifierKeyValidationRequestContext, NullifierLeafPreimage, NullifierNonExistentReadRequestHintsBuilder, NullifierReadRequestHintsBuilder, @@ -117,6 +116,7 @@ import { RootParityInputs, RootRollupInputs, RootRollupPublicInputs, + ScopedNullifierKeyValidationRequest, ScopedReadRequest, SideEffect, StateDiffHints, @@ -211,13 +211,8 @@ function makeNullifierKeyValidationRequest(seed: number): NullifierKeyValidation return new NullifierKeyValidationRequest(makePoint(seed), fr(seed + 2)); } -/** - * Creates arbitrary NullifierKeyValidationRequestContext from the given seed. - * @param seed - The seed to use for generating the NullifierKeyValidationRequestContext. - * @returns A NullifierKeyValidationRequestContext. - */ -function makeNullifierKeyValidationRequestContext(seed: number): NullifierKeyValidationRequestContext { - return new NullifierKeyValidationRequestContext(makePoint(seed), fr(seed + 2), makeAztecAddress(seed + 4)); +function makeScopedNullifierKeyValidationRequest(seed: number): ScopedNullifierKeyValidationRequest { + return new ScopedNullifierKeyValidationRequest(makeNullifierKeyValidationRequest(seed), makeAztecAddress(seed + 4)); } /** @@ -278,7 +273,7 @@ export function makeValidationRequests(seed = 1) { makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x80), makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x90), makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x95), - makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, makeNullifierKeyValidationRequestContext, seed + 0x100), + makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, makeScopedNullifierKeyValidationRequest, seed + 0x100), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, makePublicDataRead, seed + 0xe00), ); } 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 50f0c918a9d..117c095eec4 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -56,7 +56,6 @@ import { type NoteHashReadRequestHints, Nullifier, NullifierKeyValidationRequest, - NullifierKeyValidationRequestContext, type NullifierLeafPreimage, type NullifierNonExistentReadRequestHints, type NullifierReadRequestHints, @@ -108,6 +107,7 @@ import { ScopedL2ToL1Message, ScopedNoteHash, ScopedNullifier, + ScopedNullifierKeyValidationRequest, ScopedReadRequest, type SettledReadHint, SideEffect, @@ -143,7 +143,6 @@ import { type Field as NoirField, type GrumpkinPoint as NoirPoint, type NoteHash as NoteHashNoir, - type NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, type NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, type Nullifier as NullifierNoir, type PrivateAccumulatedData as PrivateAccumulatedDataNoir, @@ -157,6 +156,7 @@ import { type RollupValidationRequests as RollupValidationRequestsNoir, type ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, type ScopedNoteHash as ScopedNoteHashNoir, + type ScopedNullifierKeyValidationRequest as ScopedNullifierKeyValidationRequestNoir, type ScopedNullifier as ScopedNullifierNoir, type ScopedReadRequest as ScopedReadRequestNoir, type SideEffect as SideEffectNoir, @@ -694,32 +694,20 @@ export function mapNullifierKeyValidationRequestFromNoir( ); } -/** - * Maps a NullifierKeyValidationRequest to a noir NullifierKeyValidationRequest. - * @param request - The NullifierKeyValidationRequest. - * @returns The noir NullifierKeyValidationRequest. - */ -export function mapNullifierKeyValidationRequestContextToNoir( - request: NullifierKeyValidationRequestContext, -): NullifierKeyValidationRequestContextNoir { +function mapScopedNullifierKeyValidationRequestToNoir( + request: ScopedNullifierKeyValidationRequest, +): ScopedNullifierKeyValidationRequestNoir { return { - master_nullifier_public_key: mapPointToNoir(request.masterNullifierPublicKey), - app_nullifier_secret_key: mapFieldToNoir(request.appNullifierSecretKey), + request: mapNullifierKeyValidationRequestToNoir(request.request), contract_address: mapAztecAddressToNoir(request.contractAddress), }; } -/** - * Maps a noir NullifierKeyValidationRequestContext to NullifierKeyValidationRequestContext. - * @param request - The noir NullifierKeyValidationRequestContext. - * @returns The TS NullifierKeyValidationRequestContext. - */ -export function mapNullifierKeyValidationRequestContextFromNoir( - request: NullifierKeyValidationRequestContextNoir, -): NullifierKeyValidationRequestContext { - return new NullifierKeyValidationRequestContext( - mapPointFromNoir(request.master_nullifier_public_key), - mapFieldFromNoir(request.app_nullifier_secret_key), +function mapScopedNullifierKeyValidationRequestFromNoir( + request: ScopedNullifierKeyValidationRequestNoir, +): ScopedNullifierKeyValidationRequest { + return new ScopedNullifierKeyValidationRequest( + mapNullifierKeyValidationRequestFromNoir(request.request), mapAztecAddressFromNoir(request.contract_address), ); } @@ -1045,7 +1033,7 @@ function mapValidationRequestsToNoir(requests: ValidationRequests): ValidationRe ), nullifier_key_validation_requests: mapTuple( requests.nullifierKeyValidationRequests, - mapNullifierKeyValidationRequestContextToNoir, + mapScopedNullifierKeyValidationRequestToNoir, ), public_data_reads: mapTuple(requests.publicDataReads, mapPublicDataReadToNoir), }; @@ -1072,7 +1060,7 @@ function mapValidationRequestsFromNoir(requests: ValidationRequestsNoir): Valida mapTupleFromNoir( requests.nullifier_key_validation_requests, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - mapNullifierKeyValidationRequestContextFromNoir, + mapScopedNullifierKeyValidationRequestFromNoir, ), mapTupleFromNoir(requests.public_data_reads, MAX_PUBLIC_DATA_READS_PER_TX, mapPublicDataReadFromNoir), ); diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index c859d3bde83..0947b326c79 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -9,10 +9,10 @@ import { type MAX_UNENCRYPTED_LOGS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, - type NullifierKeyValidationRequestContext, type PrivateKernelCircuitPublicInputs, PrivateKernelTailHints, type ScopedNullifier, + type ScopedNullifierKeyValidationRequest, type ScopedReadRequest, type SideEffect, type SideEffectType, @@ -75,7 +75,7 @@ function getNullifierReadRequestHints( async function getMasterNullifierSecretKeys( nullifierKeyValidationRequests: Tuple< - NullifierKeyValidationRequestContext, + ScopedNullifierKeyValidationRequest, typeof MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX >, oracle: ProvingDataOracle, From 80b157ea925bb0e05ec236a4de9c74ca95bb8ffe Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Wed, 8 May 2024 08:33:53 +0000 Subject: [PATCH 12/13] Rename constants. --- l1-contracts/src/core/libraries/ConstantsGen.sol | 9 +++++---- yarn-project/circuits.js/src/constants.gen.ts | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 877ce019b9f..bf901bbab90 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -116,16 +116,17 @@ library Constants { uint256 internal constant APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 6; uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 3; - uint256 internal constant SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; + uint256 internal constant SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; - uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; + uint256 internal constant SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = + NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; uint256 internal constant NOTE_HASH_LENGTH = 2; - uint256 internal constant NOTE_HASH_CONTEXT_LENGTH = 4; + uint256 internal constant SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; uint256 internal constant NULLIFIER_LENGTH = 3; - uint256 internal constant NULLIFIER_CONTEXT_LENGTH = 4; + uint256 internal constant SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; uint256 internal constant SIDE_EFFECT_LENGTH = 2; uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 8bb52efa0ea..8d962fbe070 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -99,16 +99,16 @@ export const GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH; export const APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; export const L1_TO_L2_MESSAGE_LENGTH = 6; export const L2_TO_L1_MESSAGE_LENGTH = 3; -export const SCOPED_L2_TO_L1_MESSAGE_LENGTH = 4; +export const SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; export const MAX_BLOCK_NUMBER_LENGTH = 2; export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; -export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; +export const SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; export const READ_REQUEST_LENGTH = 2; export const NOTE_HASH_LENGTH = 2; -export const NOTE_HASH_CONTEXT_LENGTH = 4; +export const SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; export const NULLIFIER_LENGTH = 3; -export const NULLIFIER_CONTEXT_LENGTH = 4; +export const SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; export const SIDE_EFFECT_LENGTH = 2; export const STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; export const TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; From f209309b6132330fa3824f0bba78fcb7bdd7f4de Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Wed, 8 May 2024 09:11:49 +0000 Subject: [PATCH 13/13] Fixes. --- .../src/structs/nullifier_key_validation_request.ts | 8 ++++---- .../build_private_kernel_tail_hints.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts index b371142fbf8..2d1fa9813b5 100644 --- a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts +++ b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts @@ -3,8 +3,8 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { - NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH, NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH, + SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH, } from '../constants.gen.js'; /** @@ -74,10 +74,10 @@ export class ScopedNullifierKeyValidationRequest { } toFields(): Fr[] { - const fields = [...this.request.toFields(), this.contractAddress].flat(); - if (fields.length !== NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH) { + const fields = [...this.request.toFields(), this.contractAddress]; + if (fields.length !== SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH) { throw new Error( - `Invalid number of fields for ScopedNullifierKeyValidationRequest. Expected ${NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH}, got ${fields.length}`, + `Invalid number of fields for ScopedNullifierKeyValidationRequest. Expected ${SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH}, got ${fields.length}`, ); } return fields; diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index 0947b326c79..efef31f153a 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -82,7 +82,7 @@ async function getMasterNullifierSecretKeys( ) { const keys = makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar.zero); for (let i = 0; i < nullifierKeyValidationRequests.length; ++i) { - const request = nullifierKeyValidationRequests[i]; + const request = nullifierKeyValidationRequests[i].request; if (request.isEmpty()) { break; }