diff --git a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md index 35f384bdd250..f8ae4561bf2b 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md @@ -30,26 +30,24 @@ sequenceDiagram BalanceSet->>Set: insert(note) Set->>LifeCycle: create_note(derived_slot, note) LifeCycle->>LifeCycle: note.header = NoteHeader { contract_address,
storage_slot: derived_slot, nonce: 0, note_hash_counter } - LifeCycle->>Utils: compute_slotted_note_hash(note) - Utils->>TokenNote: note.compute_note_hiding_point() - TokenNote->>Utils: note_hiding_point = MSM([G_amt, G_to, G_rand], [amount, to, randomness]) - Utils->>NoteHash: compute_slotted_note_hash(derived_slot, note_hiding_point) - NoteHash->>LifeCycle: slotted_note_hash = CURVE_ADD(derived_slot_point, note_hiding_point).x - LifeCycle->>Context: push_note_hash(slotted_note_hash) + Utils->>TokenNote: note_hiding_point = note.compute_note_hiding_point() + TokenNote->>Utils: note_hash = note_hiding_point.x + LifeCycle->>Context: push_note_hash(note_hash) end - Context->>Kernel: siloed_note_hash = H(contract_address, slotted_note_hash) + Context->>Kernel: unique_note_hash = H(nonce, note_hash) + Context->>Kernel: siloed_note_hash = H(contract_address, unique_note_hash) ``` Notice the `siloed_note_hash` at the very end. It's a hash that will be inserted into the note hashes tree. To clarify what this really is, we "unroll" the values to their simplest components. This gives us a better idea around what is actually inserted into the tree. ```rust -siloed_note_hash = H(contract_address, slotted_note_hash) -siloed_note_hash = H(contract_address, CURVE_ADD(derived_slot_point, note_hiding_point).x) -siloed_note_hash = H(contract_address, CURVE_ADD(MSM([G_slot], [derived_slot]), note_hiding_point).x) -siloed_note_hash = H(contract_address, CURVE_ADD(MSM([G_slot], [derived_slot]), MSM([G_amt, G_to, G_rand], [amount, to, randomness])).x) +siloed_note_hash = H(contract_address, unique_note_hash) +siloed_note_hash = H(contract_address, H(nonce, note_hash)) +siloed_note_hash = H(contract_address, H(H(tx_hash, note_index_in_tx), note_hash)) +siloed_note_hash = H(contract_address, H(H(tx_hash, note_index_in_tx), MSM([G_amt, G_to, G_rand, G_slot], [amount, to, randomness, derived_slot]).x)) ``` -CURVE_ADD is a point addition and MSM is a multi scalar multiplication on a grumpkin curve and G_* values are generators. +MSM is a multi scalar multiplication on a grumpkin curve and G_* values are generators. And `to` is the actor who receives the note, `amount` of the note and `randomness` is the randomness used to make the note hiding. Without the `randomness` the note could just as well be plaintext (computational cost of a preimage attack would be trivial in such a case). diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 52880c1e67e4..5bcabb1784e5 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -1,7 +1,7 @@ use crate::context::{PrivateContext, PublicContext}; use crate::note::{ - note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_slotted_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission + note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption, + note_emission::NoteEmission }; use crate::oracle::notes::{notify_created_note, notify_nullified_note}; @@ -15,7 +15,8 @@ pub fn create_note( let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; note.set_header(header); - let slotted_note_hash = compute_slotted_note_hash(*note); + // TODO(#7771): inject compute_note_hash(...) func to notes with macros. + let note_hash = note.compute_note_hiding_point().x; let serialized_note = Note::serialize_content(*note); assert( @@ -23,13 +24,13 @@ pub fn create_note( storage_slot, Note::get_note_type_id(), serialized_note, - slotted_note_hash, + note_hash, note_hash_counter ) == 0 ); - context.push_note_hash(slotted_note_hash); + context.push_note_hash(note_hash); NoteEmission::new(*note) } @@ -43,9 +44,10 @@ pub fn create_note_hash_from_public( // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0 let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 }; note.set_header(header); - let slotted_note_hash = compute_slotted_note_hash(*note); + // TODO(#7771): inject compute_note_hash(...) func to notes with macros. + let note_hash = note.compute_note_hiding_point().x; - context.push_note_hash(slotted_note_hash); + context.push_note_hash(note_hash); } pub fn destroy_note( diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index b40a19d18cb0..8bce7674865c 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -12,22 +12,6 @@ use dep::protocol_types::{ }; use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; -pub fn compute_slotted_note_hash(note: Note) -> Field where Note: NoteInterface { - let storage_slot = note.get_header().storage_slot; - let note_hiding_point = note.compute_note_hiding_point(); - - // 1. We derive the storage slot point by multiplying the storage slot with the generator G_slot. - // We use the unsafe version because the multi_scalar_mul will constrain the scalars. - let storage_slot_scalar = from_field_unsafe(storage_slot); - let storage_slot_point = multi_scalar_mul([G_slot], [storage_slot_scalar]); - - // 2. Then we compute the slotted note hiding point by adding the storage slot point to the note hiding point. - let slotted_note_hiding_point = storage_slot_point + note_hiding_point; - - // 3. Finally, we return the slotted note hash which is the x-coordinate of the slotted note hiding point. - slotted_note_hiding_point.x -} - pub fn compute_siloed_nullifier( note_with_header: Note, context: &mut PrivateContext @@ -39,14 +23,15 @@ pub fn compute_siloed_nullifier( } pub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface { - let slotted_note_hash = compute_slotted_note_hash(note); + // TODO(#7771): inject compute_note_hash(...) func to notes with macros. + let note_hash = note.compute_note_hiding_point().x; let nonce = note.get_header().nonce; let counter = note.get_header().note_hash_counter; if counter != 0 { - slotted_note_hash + note_hash } else { - compute_unique_note_hash(nonce, slotted_note_hash) + compute_unique_note_hash(nonce, note_hash) } } @@ -59,12 +44,13 @@ pub fn compute_note_hash_for_consumption(note: Not // the same transaction: (note_hash_counter != 0) & (nonce != 0) // 3. The note was inserted in a previous transaction: (note_hash_counter == 0) & (nonce != 0) - let slotted_note_hash = compute_slotted_note_hash(note); + // TODO(#7771): inject compute_note_hash(...) func to notes with macros. + let note_hash = note.compute_note_hiding_point().x; if header.nonce == 0 { // Case 1. - // If a note is transient, we just read the slotted_note_hash (kernel will silo by contract address). - slotted_note_hash + // If a note is transient, we just read the note_hash (kernel will hash it with nonce and silo by contract address). + note_hash } else { // Case 2: If a note is non-revertible, and is nullified by a revertible nullifier, we cannot squash them in the // private reset circuit. Because if the tx reverts, we will have to keep the note hash and throw away the @@ -78,7 +64,7 @@ pub fn compute_note_hash_for_consumption(note: Not // tree) created in a previous TX. So we need the siloed_note_hash which has already been hashed with // nonce and then contract address. This hash will match the existing leaf in the note hash // tree, so the kernel can just perform a membership check directly on this hash/leaf. - let unique_note_hash = compute_unique_note_hash(header.nonce, slotted_note_hash); + let unique_note_hash = compute_unique_note_hash(header.nonce, note_hash); compute_siloed_note_hash(header.contract_address, unique_note_hash) // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is // "siloed" by contract address. When a note hash is computed solely for the purpose of @@ -100,8 +86,9 @@ pub fn compute_note_hash_and_optionally_a_nullifier( _storage_slot: Field, _note_type_id: Field, _serialized_note: [Field; N], - _slotted_note_hash: Field, + _note_hash: Field, _counter: u32 ) -> Field {} @@ -15,27 +15,21 @@ unconstrained pub fn notify_created_note( storage_slot: Field, note_type_id: Field, serialized_note: [Field; N], - slotted_note_hash: Field, + note_hash: Field, counter: u32 ) -> Field { - notify_created_note_oracle( - storage_slot, - note_type_id, - serialized_note, - slotted_note_hash, - counter - ) + notify_created_note_oracle(storage_slot, note_type_id, serialized_note, note_hash, counter) } #[oracle(notifyNullifiedNote)] -unconstrained fn notify_nullified_note_oracle(_nullifier: Field, _slotted_note_hash: Field, _counter: u32) -> Field {} +unconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) -> Field {} unconstrained pub fn notify_nullified_note( nullifier: Field, - slotted_note_hash: Field, + note_hash: Field, counter: u32 ) -> Field { - notify_nullified_note_oracle(nullifier, slotted_note_hash, counter) + notify_nullified_note_oracle(nullifier, note_hash, counter) } #[oracle(getNotes)] diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr index 6ce7feabce5c..12ba6715de84 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr @@ -95,8 +95,8 @@ unconstrained pub fn add_nullifiers(contractAddress: AztecAddress, nullifiers: [ oracle_add_nullifiers(contractAddress, nullifiers) } -unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, slotted_note_hashes: [Field]) { - oracle_add_note_hashes(contractAddress, slotted_note_hashes) +unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, note_hashes: [Field]) { + oracle_add_note_hashes(contractAddress, note_hashes) } unconstrained pub fn get_function_selector() -> FunctionSelector { @@ -180,7 +180,7 @@ unconstrained fn oracle_assert_private_call_fails( unconstrained fn oracle_add_nullifiers(contractAddress: AztecAddress, nullifiers: [Field]) {} #[oracle(addNoteHashes)] -unconstrained fn oracle_add_note_hashes(contractAddress: AztecAddress, slotted_note_hashes: [Field]) {} +unconstrained fn oracle_add_note_hashes(contractAddress: AztecAddress, note_hashes: [Field]) {} #[oracle(getFunctionSelector)] unconstrained fn oracle_get_function_selector() -> FunctionSelector {} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 923373f2d23d..5a1437572e1d 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -12,10 +12,7 @@ use crate::test::helpers::{cheatcodes, utils::{apply_side_effects_private, Deplo use crate::keys::constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}; use crate::hash::{hash_args, hash_args_array}; -use crate::note::{ - note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_slotted_note_hash, compute_note_hash_for_consumption} -}; +use crate::note::{note_header::NoteHeader, note_interface::NoteInterface}; use crate::oracle::{execution::{get_block_number, get_contract_address}, notes::notify_created_note}; struct TestEnvironment {} @@ -219,14 +216,15 @@ impl TestEnvironment { let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; note.set_header(header); - let slotted_note_hash = compute_slotted_note_hash(*note); + // TODO(#7771): inject compute_note_hash(...) func to notes with macros. + let note_hash = note.compute_note_hiding_point().x; let serialized_note = Note::serialize_content(*note); assert( notify_created_note( storage_slot, Note::get_note_type_id(), serialized_note, - slotted_note_hash, + note_hash, note_hash_counter ) == 0 diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index c6fdf0b9da0f..5cd3a8e7cacd 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -91,7 +91,7 @@ contract PendingNoteHashes { // Nested/inner function to create and insert a note // TESTING: inserts a static randomness value to test notes with - // the same slotted note hash are dealt with correctly + // the same note hash are dealt with correctly #[aztec(private)] fn insert_note_static_randomness( amount: Field, diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index caebffbcf759..6a2d4e94fe25 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -7,7 +7,7 @@ use dep::aztec::{ // TODO(#7738): Nuke the following imports use dep::aztec::{ - generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd}, + generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd, G_slot}, protocol_types::{point::Point, scalar::Scalar} }; use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; @@ -60,16 +60,20 @@ impl NoteInterface for TokenNote { // TODO(#7738): Nuke this function and have it auto-generated by macros fn compute_note_hiding_point(self) -> Point { + assert(self.header.storage_slot != 0, "Storage slot must be set before computing note hiding point"); + + // TODO(#7772): decompose amount with from_field_unsafe or constrain it fits into 1 limb + let amount_scalar = Scalar { + lo: self.amount.to_integer(), + hi: 0 + }; + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash); let randomness_scalar = from_field_unsafe(self.randomness); + let slot_scalar = from_field_unsafe(self.header.storage_slot); multi_scalar_mul( - [G_amt, G_npk, G_rnd], - [Scalar { - lo: self.amount.to_integer(), - hi: 0 - }, - npk_m_hash_scalar, - randomness_scalar] + [G_amt, G_npk, G_rnd, G_slot], + [amount_scalar, npk_m_hash_scalar, randomness_scalar, slot_scalar] ) } } diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr index 716767f2533b..527024d7ea3f 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr @@ -469,35 +469,41 @@ contract TokenWithRefunds { // to the user in the `complete_refund(...)` function. storage.balances.sub(user, U128::from_integer(funded_amount)).emit(encode_and_encrypt_note_with_keys(&mut context, user_ovpk, user_ivpk, user)); - // 4. We create the partial notes for the fee payer and the user. + // 4. Now we "manually" compute the slots (by setting the slots we insert the notes to the balances map under + // the correct keys) + let fee_payer_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, fee_payer); + let user_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, user); + + // 5. We create the partial notes for the fee payer and the user. // --> Called "partial" because they don't have the amount set yet (that will be done in `complete_refund(...)`). let fee_payer_partial_note = TokenNote { - header: NoteHeader::empty(), + header: NoteHeader { + contract_address: AztecAddress::zero(), + nonce: 0, + storage_slot: fee_payer_balances_slot, + note_hash_counter: 0 + }, amount: U128::zero(), npk_m_hash: fee_payer_npk_m_hash, randomness: fee_payer_randomness }; let user_partial_note = TokenNote { - header: NoteHeader::empty(), + header: NoteHeader { + contract_address: AztecAddress::zero(), + nonce: 0, + storage_slot: user_balances_slot, + note_hash_counter: 0 + }, amount: U128::zero(), npk_m_hash: user_npk_m_hash, randomness: user_randomness }; - // 5. Now we get the note hiding points. + // 6. Now we get the note hiding points. let mut fee_payer_point = fee_payer_partial_note.to_note_hiding_point(); let mut user_point = user_partial_note.to_note_hiding_point(); - // 6. Now we "manually" compute the slot points and add them to hiding points. - let fee_payer_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, fee_payer); - let user_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, user); - - // 7. We add the slot to the points --> this way we insert the notes into the balances Map under the respective key. - // TODO(#7753): Consider making slots part of the initital note hiding point creation. - fee_payer_point.add_slot(fee_payer_balances_slot); - user_point.add_slot(user_balances_slot); - - // 8. Set the public teardown function to `complete_refund(...)`. Public teardown is the only time when a public + // 7. Set the public teardown function to `complete_refund(...)`. Public teardown is the only time when a public // function has access to the final transaction fee, which is needed to compute the actual refund amount. context.set_public_teardown_function( context.this_address(), @@ -513,14 +519,14 @@ contract TokenWithRefunds { #[aztec(public)] #[aztec(internal)] fn complete_refund( - // TODO: the following makes macros crash --> try getting it work once we migrate to metaprogramming + // TODO(#7771): the following makes macros crash --> try getting it work once we migrate to metaprogramming // mut fee_payer_point: TokenNoteHidingPoint, // mut user_point: TokenNoteHidingPoint, fee_payer_point_immutable: TokenNoteHidingPoint, user_point_immutable: TokenNoteHidingPoint, funded_amount: Field ) { - // TODO: nuke the following 2 lines once we have mutable args + // TODO(#7771): nuke the following 2 lines once we have mutable args let mut fee_payer_point = fee_payer_point_immutable; let mut user_point = user_point_immutable; diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr index c9daa1239143..f7d4666c7065 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr @@ -46,20 +46,24 @@ impl NoteInterface for TokenNote { } fn compute_note_hiding_point(self) -> Point { - // We use the unsafe version because the multi_scalar_mul will constrain the scalars. - let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash); - let randomness_scalar = from_field_unsafe(self.randomness); - // TODO(benesjan): decompose amount with from_field_unsafe or constrain it fits into limb + assert(self.header.storage_slot != 0, "Storage slot must be set before computing note hiding point"); + + // TODO(#7772): decompose amount with from_field_unsafe or constrain it fits into 1 limb let amount_scalar = Scalar { lo: self.amount.to_integer(), hi: 0 }; - // We compute the note hiding point as `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead - // of using pedersen or poseidon2 because it allows us to privately add and subtract from amount in public - // by leveraging homomorphism. + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash); + let randomness_scalar = from_field_unsafe(self.randomness); + let slot_scalar = from_field_unsafe(self.header.storage_slot); + // We compute the note hiding point as: + // `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness + G_slot * slot` + // instead of using pedersen or poseidon2 because it allows us to privately add and subtract from amount + // in public by leveraging homomorphism. multi_scalar_mul( - [G_amt, G_npk, G_rnd], - [amount_scalar, npk_m_hash_scalar, randomness_scalar] + [G_amt, G_npk, G_rnd, G_slot], + [amount_scalar, npk_m_hash_scalar, randomness_scalar, slot_scalar] ) } } @@ -82,7 +86,7 @@ impl TokenNoteHidingPoint { } fn add_amount(&mut self, amount: U128) { - // TODO(benesjan): decompose amount with from_field_unsafe or constrain it fits into limb + // TODO(#7772): decompose amount with from_field_unsafe or constrain it fits into 1 limb let amount_scalar = Scalar { lo: amount.to_integer(), hi: 0 }; self.inner = multi_scalar_mul([G_amt], [amount_scalar]) + self.inner; } 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 d778c72d5043..a4dd938668be 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 @@ -55,21 +55,21 @@ mod tests { global contract_address = AztecAddress::from_field(123); // Create 4 note hashes. 10 and 11 are settled. 12 and 13 are pending. - global slotted_note_hashes = [10, 11, 12, 13]; - global note_hashes = slotted_note_hashes.map(|n| compute_siloed_note_hash(contract_address, n)); + global note_hashes = [10, 11, 12, 13]; + global siloed_note_hashes = note_hashes.map(|n| compute_siloed_note_hash(contract_address, n)); // Create 5 read requests. 0 and 3 are reading settled note hashes. 1, 2 and 4 are reading pending note hashes. global read_requests = [ - ReadRequest { value: slotted_note_hashes[1], counter: 11 }.scope(contract_address), // settled - ReadRequest { value: slotted_note_hashes[3], counter: 13 }.scope(contract_address), // pending - ReadRequest { value: slotted_note_hashes[2], counter: 39 }.scope(contract_address), // pending - ReadRequest { value: slotted_note_hashes[0], counter: 46 }.scope(contract_address), // settled - ReadRequest { value: slotted_note_hashes[3], counter: 78 }.scope(contract_address), // pending + ReadRequest { value: note_hashes[1], counter: 11 }.scope(contract_address), // settled + ReadRequest { value: note_hashes[3], counter: 13 }.scope(contract_address), // pending + ReadRequest { value: note_hashes[2], counter: 39 }.scope(contract_address), // pending + ReadRequest { value: note_hashes[0], counter: 46 }.scope(contract_address), // settled + ReadRequest { value: note_hashes[3], counter: 78 }.scope(contract_address), // pending ]; global pending_values = [ - NoteHash { value: slotted_note_hashes[2], counter: 2, }.scope(contract_address), - NoteHash { value: slotted_note_hashes[3], counter: 8, }.scope(contract_address), + NoteHash { value: note_hashes[2], counter: 2, }.scope(contract_address), + NoteHash { value: note_hashes[3], counter: 8, }.scope(contract_address), ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, @@ -78,8 +78,8 @@ mod tests { ]; global leaf_preimages = [ - NoteHashLeafPreimage { value: note_hashes[0] }, - NoteHashLeafPreimage { value: note_hashes[1] }, + NoteHashLeafPreimage { value: siloed_note_hashes[0] }, + NoteHashLeafPreimage { value: siloed_note_hashes[1] }, ]; fn read_request_statuses() -> [ReadRequestStatus; 5] { 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 bd82a5089529..ae9a9f7d9844 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -45,8 +45,8 @@ fn compute_note_hash_nonce(tx_hash: Field, note_index_in_tx: u32) -> Field { ) } -pub fn compute_unique_note_hash(nonce: Field, slotted_note_hash: Field) -> Field { - let inputs = [nonce, slotted_note_hash]; +pub fn compute_unique_note_hash(nonce: Field, note_hash: Field) -> Field { + let inputs = [nonce, note_hash]; poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH) } @@ -60,6 +60,8 @@ pub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> F ) } +/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way +/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts. pub fn silo_note_hash(note_hash: ScopedNoteHash, tx_hash: Field, note_index_in_tx: u32) -> Field { if note_hash.contract_address.is_zero() { 0 diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index a65fbc25f168..7f5c0e8b48b3 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -522,12 +522,18 @@ fn generate_compute_note_hiding_point( impl_span: Option, empty_spans: bool, ) -> Result { + // TODO(#7771): update this to do only 1 MSM call let function_source = format!( - " + r#" fn compute_note_hiding_point(self: {}) -> aztec::protocol_types::point::Point {{ - aztec::hash::pedersen_commitment(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HIDING_POINT) + assert(self.header.storage_slot != 0, "Storage slot must be set before computing note hiding point"); + let slot_scalar = dep::std::hash::from_field_unsafe(self.header.storage_slot); + + let point_before_slotting = aztec::hash::pedersen_commitment(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HIDING_POINT); + let slot_point = dep::std::embedded_curve_ops::multi_scalar_mul([dep::aztec::generators::G_slot], [slot_scalar]); + point_before_slotting + slot_point }} - ", + "#, note_type ); let (function_ast, errors) = parse_program(&function_source, empty_spans); diff --git a/yarn-project/circuits.js/src/hash/hash.test.ts b/yarn-project/circuits.js/src/hash/hash.test.ts index 3f808d62a44a..6a9fb665d1e2 100644 --- a/yarn-project/circuits.js/src/hash/hash.test.ts +++ b/yarn-project/circuits.js/src/hash/hash.test.ts @@ -27,8 +27,8 @@ describe('hash', () => { it('computes unique note hash', () => { const nonce = new Fr(123n); - const slottedNoteHash = new Fr(456); - const res = computeUniqueNoteHash(nonce, slottedNoteHash); + const noteHash = new Fr(456); + const res = computeUniqueNoteHash(nonce, noteHash); expect(res).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/hash/hash.ts b/yarn-project/circuits.js/src/hash/hash.ts index ecb3ac53350a..6226ee72183a 100644 --- a/yarn-project/circuits.js/src/hash/hash.ts +++ b/yarn-project/circuits.js/src/hash/hash.ts @@ -55,11 +55,11 @@ export function siloNoteHash(contract: AztecAddress, uniqueNoteHash: Fr): Fr { * Computes a unique note hash. * @dev Includes a nonce which contains data that guarantees the resulting note hash will be unique. * @param nonce - A nonce (typically derived from tx hash and note hash index in the tx). - * @param slottedNoteHash - A slotted note hash. + * @param noteHash - A note hash. * @returns A unique note hash. */ -export function computeUniqueNoteHash(nonce: Fr, slottedNoteHash: Fr): Fr { - return poseidon2HashWithSeparator([nonce, slottedNoteHash], GeneratorIndex.UNIQUE_NOTE_HASH); +export function computeUniqueNoteHash(nonce: Fr, noteHash: Fr): Fr { + return poseidon2HashWithSeparator([nonce, noteHash], GeneratorIndex.UNIQUE_NOTE_HASH); } /** 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 59638719276f..8117be97c140 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 @@ -39,7 +39,7 @@ describe('buildNoteHashReadRequestHints', () => { let numSettledReads = 0; let futureNoteHashes: ScopedNoteHash[]; - const slottedNoteHash = (index: number) => index + 9999; + const getNoteHashValue = (index: number) => index + 9999; const makeReadRequest = (value: number, counter = 2) => new ReadRequest(new Fr(value), counter).scope(contractAddress); @@ -49,7 +49,7 @@ describe('buildNoteHashReadRequestHints', () => { const readPendingNoteHash = (noteHashIndex: number) => { const readRequestIndex = numReadRequests; const hintIndex = numPendingReads; - noteHashReadRequests[readRequestIndex] = makeReadRequest(slottedNoteHash(noteHashIndex)); + noteHashReadRequests[readRequestIndex] = makeReadRequest(getNoteHashValue(noteHashIndex)); expectedHints.readRequestStatuses[readRequestIndex] = ReadRequestStatus.pending(hintIndex); expectedHints.pendingReadHints[hintIndex] = new PendingReadHint(readRequestIndex, noteHashIndex); numReadRequests++; @@ -89,7 +89,7 @@ describe('buildNoteHashReadRequestHints', () => { beforeEach(() => { noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); - noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(slottedNoteHash(i))); + noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(getNoteHashValue(i))); noteHashLeafIndexMap = new Map(); expectedHints = NoteHashReadRequestHintsBuilder.empty( MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -100,7 +100,7 @@ describe('buildNoteHashReadRequestHints', () => { numSettledReads = 0; futureNoteHashes = new Array(MAX_NOTE_HASHES_PER_TX) .fill(null) - .map((_, i) => makeNoteHash(slottedNoteHash(i + MAX_NOTE_HASHES_PER_TX))); + .map((_, i) => makeNoteHash(getNoteHashValue(i + MAX_NOTE_HASHES_PER_TX))); }); it('builds empty hints', async () => { diff --git a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts index 3c369d8bd599..c379ae088aa7 100644 --- a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts @@ -188,7 +188,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteLogsSquashedExcept(1); }); - it('Squash! Aztec.nr function can "create" 2 notes with the same slotted note hash and "nullify" 1 in the same TX', async () => { + it('Squash! Aztec.nr function can "create" 2 notes with the same note hash and "nullify" 1 in the same TX', async () => { // Kernel will squash one noteHash and its nullifier, where two notes with the same inner hash exist. // The other note will become persistent! // Realistic way to describe this test is "Mint notes A and B, then burn note A in the same transaction" diff --git a/yarn-project/pxe/src/database/incoming_note_dao.test.ts b/yarn-project/pxe/src/database/incoming_note_dao.test.ts index 00c70ea296e1..398263165d6f 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.test.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.test.ts @@ -11,7 +11,7 @@ export const randomIncomingNoteDao = ({ storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), - slottedNoteHash = Fr.random(), + noteHash = Fr.random(), siloedNullifier = Fr.random(), index = Fr.random().toBigInt(), ivpkM = Point.random(), @@ -23,7 +23,7 @@ export const randomIncomingNoteDao = ({ noteTypeId, txHash, nonce, - slottedNoteHash, + noteHash, siloedNullifier, index, ivpkM, diff --git a/yarn-project/pxe/src/database/incoming_note_dao.ts b/yarn-project/pxe/src/database/incoming_note_dao.ts index fb51b025c8f5..cba1df864f6d 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.ts @@ -23,10 +23,10 @@ export class IncomingNoteDao implements NoteData { /** The nonce of the note. */ public nonce: Fr, /** - * Slotted note hash of the note. This is customizable by the app circuit. + * A hash of the note. This is customizable by the app circuit. * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash. */ - public slottedNoteHash: Fr, + public noteHash: Fr, /** * The nullifier of the note (siloed by contract address). * Note: Might be set as 0 if the note was added to PXE as nullified. @@ -46,7 +46,7 @@ export class IncomingNoteDao implements NoteData { this.noteTypeId, this.txHash.buffer, this.nonce, - this.slottedNoteHash, + this.noteHash, this.siloedNullifier, this.index, this.ivpkM, @@ -61,7 +61,7 @@ export class IncomingNoteDao implements NoteData { const noteTypeId = reader.readObject(NoteSelector); const txHash = reader.readObject(TxHash); const nonce = Fr.fromBuffer(reader); - const slottedNoteHash = Fr.fromBuffer(reader); + const noteHash = Fr.fromBuffer(reader); const siloedNullifier = Fr.fromBuffer(reader); const index = toBigIntBE(reader.readBytes(32)); const publicKey = Point.fromBuffer(reader); @@ -73,7 +73,7 @@ export class IncomingNoteDao implements NoteData { noteTypeId, txHash, nonce, - slottedNoteHash, + noteHash, siloedNullifier, index, publicKey, diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts index cb404be360ba..04b2b2201f7c 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts @@ -11,21 +11,11 @@ export const randomOutgoingNoteDao = ({ storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), - slottedNoteHash = Fr.random(), + noteHash = Fr.random(), index = Fr.random().toBigInt(), ovpkM = Point.random(), }: Partial = {}) => { - return new OutgoingNoteDao( - note, - contractAddress, - storageSlot, - noteTypeId, - txHash, - nonce, - slottedNoteHash, - index, - ovpkM, - ); + return new OutgoingNoteDao(note, contractAddress, storageSlot, noteTypeId, txHash, nonce, noteHash, index, ovpkM); }; describe('Outgoing Note DAO', () => { diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.ts b/yarn-project/pxe/src/database/outgoing_note_dao.ts index 1c038e5dc48e..bfbd309ddf7e 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.ts @@ -22,10 +22,10 @@ export class OutgoingNoteDao { /** The nonce of the note. */ public nonce: Fr, /** - * Slotted note hash of the note. This is customizable by the app circuit. - * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash. + * A hash of the note. This is customizable by the app circuit. + * We can use this value to compute unique note hash and then siloed note hash. */ - public slottedNoteHash: Fr, + public noteHash: Fr, /** The location of the relevant note in the note hash tree. */ public index: bigint, /** The public key with which the note was encrypted. */ @@ -40,7 +40,7 @@ export class OutgoingNoteDao { this.noteTypeId, this.txHash.buffer, this.nonce, - this.slottedNoteHash, + this.noteHash, this.index, this.ovpkM, ]); @@ -54,7 +54,7 @@ export class OutgoingNoteDao { const noteTypeId = reader.readObject(NoteSelector); const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); const nonce = Fr.fromBuffer(reader); - const slottedNoteHash = Fr.fromBuffer(reader); + const noteHash = Fr.fromBuffer(reader); const index = toBigIntBE(reader.readBytes(32)); const publicKey = Point.fromBuffer(reader); @@ -65,7 +65,7 @@ export class OutgoingNoteDao { noteTypeId, txHash, nonce, - slottedNoteHash, + noteHash, index, publicKey, ); diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index ea92c4ff4733..2a694b167088 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -166,7 +166,7 @@ describe('Note Processor', () => { simulator.computeNoteHashAndOptionallyANullifier.mockImplementation((...args) => Promise.resolve({ - slottedNoteHash: Fr.random(), + noteHash: Fr.random(), uniqueNoteHash: Fr.random(), siloedNoteHash: pedersenHash(args[5].items), // args[5] is note innerNullifier: Fr.random(), diff --git a/yarn-project/pxe/src/note_processor/produce_note_dao.ts b/yarn-project/pxe/src/note_processor/produce_note_dao.ts index b8325f764154..5ffc396bc6ce 100644 --- a/yarn-project/pxe/src/note_processor/produce_note_dao.ts +++ b/yarn-project/pxe/src/note_processor/produce_note_dao.ts @@ -51,7 +51,7 @@ export async function produceNoteDaos( try { if (ivpkM) { - const { noteHashIndex, nonce, slottedNoteHash, siloedNullifier } = await findNoteIndexAndNullifier( + const { noteHashIndex, nonce, noteHash, siloedNullifier } = await findNoteIndexAndNullifier( simulator, noteHashes, txHash, @@ -69,7 +69,7 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, nonce, - slottedNoteHash, + noteHash, siloedNullifier, index, ivpkM, @@ -108,12 +108,12 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, incomingNote.nonce, - incomingNote.slottedNoteHash, + incomingNote.noteHash, incomingNote.index, ovpkM, ); } else { - const { noteHashIndex, nonce, slottedNoteHash } = await findNoteIndexAndNullifier( + const { noteHashIndex, nonce, noteHash } = await findNoteIndexAndNullifier( simulator, noteHashes, txHash, @@ -130,7 +130,7 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, nonce, - slottedNoteHash, + noteHash, index, ovpkM, ); @@ -170,7 +170,7 @@ export async function produceNoteDaos( * @dev Finds the index in the note hash tree by computing the note hash with different nonce and see which hash for * the current tx matches this value. * @remarks This method assists in identifying spent notes in the note hash tree. - * @param noteHashes - Note hashes in the tx. One of them should correspond to the note we are looking for + * @param siloedNoteHashes - Note hashes in the tx. One of them should correspond to the note we are looking for * @param txHash - Hash of a tx the note was emitted in. * @param l1NotePayload - The note payload. * @param excludedIndices - Indices that have been assigned a note in the same tx. Notes in a tx can have the same @@ -181,7 +181,7 @@ export async function produceNoteDaos( */ async function findNoteIndexAndNullifier( simulator: AcirSimulator, - noteHashes: Fr[], + siloedNoteHashes: Fr[], txHash: TxHash, { contractAddress, storageSlot, noteTypeId, note }: L1NotePayload, excludedIndices: Set, @@ -189,23 +189,23 @@ async function findNoteIndexAndNullifier( ) { let noteHashIndex = 0; let nonce: Fr | undefined; - let slottedNoteHash: Fr | undefined; + let noteHash: Fr | undefined; let siloedNoteHash: Fr | undefined; let innerNullifier: Fr | undefined; const firstNullifier = Fr.fromBuffer(txHash.toBuffer()); - for (; noteHashIndex < noteHashes.length; ++noteHashIndex) { + for (; noteHashIndex < siloedNoteHashes.length; ++noteHashIndex) { if (excludedIndices.has(noteHashIndex)) { continue; } - const noteHash = noteHashes[noteHashIndex]; - if (noteHash.equals(Fr.ZERO)) { + const siloedNoteHashFromTxEffect = siloedNoteHashes[noteHashIndex]; + if (siloedNoteHashFromTxEffect.equals(Fr.ZERO)) { break; } const expectedNonce = computeNoteHashNonce(firstNullifier, noteHashIndex); - ({ slottedNoteHash, siloedNoteHash, innerNullifier } = await simulator.computeNoteHashAndOptionallyANullifier( + ({ noteHash, siloedNoteHash, innerNullifier } = await simulator.computeNoteHashAndOptionallyANullifier( contractAddress, expectedNonce, storageSlot, @@ -214,7 +214,7 @@ async function findNoteIndexAndNullifier( note, )); - if (noteHash.equals(siloedNoteHash)) { + if (siloedNoteHashFromTxEffect.equals(siloedNoteHash)) { nonce = expectedNonce; break; } @@ -229,7 +229,7 @@ async function findNoteIndexAndNullifier( return { noteHashIndex, nonce, - slottedNoteHash: slottedNoteHash!, + noteHash: noteHash!, siloedNullifier: siloNullifier(contractAddress, innerNullifier!), }; } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 5c61d5f975ac..d6d3e2437a78 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -350,15 +350,14 @@ export class PXEService implements PXE { } for (const nonce of nonces) { - const { slottedNoteHash, siloedNoteHash, innerNullifier } = - await this.simulator.computeNoteHashAndOptionallyANullifier( - note.contractAddress, - nonce, - note.storageSlot, - note.noteTypeId, - true, - note.note, - ); + const { noteHash, siloedNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier( + note.contractAddress, + nonce, + note.storageSlot, + note.noteTypeId, + true, + note.note, + ); const index = await this.node.findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, siloedNoteHash); if (index === undefined) { @@ -379,7 +378,7 @@ export class PXEService implements PXE { note.noteTypeId, note.txHash, nonce, - slottedNoteHash, + noteHash, siloedNullifier, index, owner.publicKeys.masterIncomingViewingPublicKey, @@ -401,15 +400,14 @@ export class PXEService implements PXE { } for (const nonce of nonces) { - const { slottedNoteHash, siloedNoteHash, innerNullifier } = - await this.simulator.computeNoteHashAndOptionallyANullifier( - note.contractAddress, - nonce, - note.storageSlot, - note.noteTypeId, - false, - note.note, - ); + const { noteHash, siloedNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier( + note.contractAddress, + nonce, + note.storageSlot, + note.noteTypeId, + false, + note.note, + ); if (!innerNullifier.equals(Fr.ZERO)) { throw new Error('Unexpectedly received non-zero nullifier.'); @@ -428,7 +426,7 @@ export class PXEService implements PXE { note.noteTypeId, note.txHash, nonce, - slottedNoteHash, + noteHash, Fr.ZERO, // We are not able to derive index, owner.publicKeys.masterIncomingViewingPublicKey, diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index deab8e878d7a..5798a955888e 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -84,12 +84,12 @@ export class SimulatorOracle implements DBOracle { status, scopes, }); - return noteDaos.map(({ contractAddress, storageSlot, nonce, note, slottedNoteHash, siloedNullifier, index }) => ({ + return noteDaos.map(({ contractAddress, storageSlot, nonce, note, noteHash, siloedNullifier, index }) => ({ contractAddress, storageSlot, nonce, note, - slottedNoteHash, + noteHash, siloedNullifier, // PXE can use this index to get full MembershipWitness index, diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 2c6de5ba7f69..cab30078dc7a 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -247,14 +247,14 @@ export class Oracle { [storageSlot]: ACVMField[], [noteTypeId]: ACVMField[], note: ACVMField[], - [slottedNoteHash]: ACVMField[], + [noteHash]: ACVMField[], [counter]: ACVMField[], ): ACVMField { this.typedOracle.notifyCreatedNote( fromACVMField(storageSlot), NoteSelector.fromField(fromACVMField(noteTypeId)), note.map(fromACVMField), - fromACVMField(slottedNoteHash), + fromACVMField(noteHash), +counter, ); return toACVMField(0); @@ -262,10 +262,10 @@ export class Oracle { async notifyNullifiedNote( [innerNullifier]: ACVMField[], - [slottedNoteHash]: ACVMField[], + [noteHash]: ACVMField[], [counter]: ACVMField[], ): Promise { - await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(slottedNoteHash), +counter); + await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(noteHash), +counter); return toACVMField(0); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 872e0b2b5afc..1b9dae81e8aa 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -27,8 +27,8 @@ export interface NoteData { storageSlot: Fr; /** The nonce of the note. */ nonce: Fr; - /** The slotted note hash of the note. */ - slottedNoteHash: Fr; + /** A hash of the note. */ + noteHash: Fr; /** The corresponding nullifier of the note. Undefined for pending notes. */ siloedNullifier?: Fr; /** The note's leaf index in the note hash tree. Undefined for pending notes. */ @@ -158,17 +158,11 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNotes'); } - notifyCreatedNote( - _storageSlot: Fr, - _noteTypeId: NoteSelector, - _note: Fr[], - _slottedNoteHash: Fr, - _counter: number, - ): void { + notifyCreatedNote(_storageSlot: Fr, _noteTypeId: NoteSelector, _note: Fr[], _noteHash: Fr, _counter: number): void { throw new OracleMethodNotAvailableError('notifyCreatedNote'); } - notifyNullifiedNote(_innerNullifier: Fr, _slottedNoteHash: Fr, _counter: number): Promise { + notifyNullifiedNote(_innerNullifier: Fr, _noteHash: Fr, _counter: number): Promise { throw new OracleMethodNotAvailableError('notifyNullifiedNote'); } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index d682e12553d8..79b1f913ef4d 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -136,7 +136,6 @@ export class ClientExecutionContext extends ViewDataOracle { /** * Get the data for the newly created notes. - * @param slottedNoteHashes - Slotted note hashes for the notes. */ public getNewNotes(): NoteAndSlot[] { return this.newNotes; @@ -277,7 +276,7 @@ export class ClientExecutionContext extends ViewDataOracle { notes.forEach(n => { if (n.index !== undefined) { - const uniqueNoteHash = computeUniqueNoteHash(n.nonce, n.slottedNoteHash); + const uniqueNoteHash = computeUniqueNoteHash(n.nonce, n.noteHash); const siloedNoteHash = siloNoteHash(n.contractAddress, uniqueNoteHash); this.noteHashLeafIndexMap.set(siloedNoteHash.toBigInt(), n.index); } @@ -293,14 +292,14 @@ export class ClientExecutionContext extends ViewDataOracle { * @param storageSlot - The storage slot. * @param noteTypeId - The type ID of the note. * @param noteItems - The items to be included in a Note. - * @param slottedNoteHash - The slotted note hash of the new note. + * @param noteHash - A hash of the new note. * @returns */ public override notifyCreatedNote( storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], - slottedNoteHash: Fr, + noteHash: Fr, counter: number, ) { const note = new Note(noteItems); @@ -311,7 +310,7 @@ export class ClientExecutionContext extends ViewDataOracle { nonce: Fr.ZERO, // Nonce cannot be known during private execution. note, siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note. - slottedNoteHash, + noteHash, }, counter, ); @@ -326,13 +325,13 @@ export class ClientExecutionContext extends ViewDataOracle { * Adding a siloed nullifier into the current set of all pending nullifiers created * within the current transaction/execution. * @param innerNullifier - The pending nullifier to add in the list (not yet siloed by contract address). - * @param slottedNoteHash - The slotted note hash of the new note. + * @param noteHash - A hash of the new note. */ - public override notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, counter: number) { + public override notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) { const nullifiedNoteHashCounter = this.noteCache.nullifyNote( this.callContext.storageContractAddress, innerNullifier, - slottedNoteHash, + noteHash, ); if (nullifiedNoteHashCounter !== undefined) { this.noteHashNullifierCounterMap.set(nullifiedNoteHashCounter, counter); diff --git a/yarn-project/simulator/src/client/execution_note_cache.ts b/yarn-project/simulator/src/client/execution_note_cache.ts index b97dfda9aebc..f8e1ec0a670e 100644 --- a/yarn-project/simulator/src/client/execution_note_cache.ts +++ b/yarn-project/simulator/src/client/execution_note_cache.ts @@ -51,7 +51,7 @@ export class ExecutionNoteCache { // The nonces will be used to create the "complete" nullifier. const updatedNotes = this.notes.map(({ note, counter }, i) => { const nonce = computeNoteHashNonce(this.txHash, i); - const uniqueNoteHash = computeUniqueNoteHash(nonce, note.slottedNoteHash); + const uniqueNoteHash = computeUniqueNoteHash(nonce, note.noteHash); return { counter, note: { ...note, nonce }, @@ -76,27 +76,27 @@ export class ExecutionNoteCache { ); } - this.#addNote({ note, counter, noteHashForConsumption: note.slottedNoteHash }); + this.#addNote({ note, counter, noteHashForConsumption: note.noteHash }); } /** * Add a nullifier to cache. It could be for a db note or a new note created during execution. * @param contractAddress - Contract address of the note. * @param innerNullifier - Inner nullifier of the note. - * @param slottedNoteHash - Slotted note hash of the note. If this value equals 0, it means the - * note being nullified is from a previous transaction (and thus not a new note). + * @param noteHash - A hash of the note. If this value equals 0, it means the note being nullified is from a previous + * transaction (and thus not a new note). */ - public nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, slottedNoteHash: Fr) { + public nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, noteHash: Fr) { const siloedNullifier = siloNullifier(contractAddress, innerNullifier); const nullifiers = this.getNullifiers(contractAddress); nullifiers.add(siloedNullifier.value); this.nullifierMap.set(contractAddress.toBigInt(), nullifiers); let nullifiedNoteHashCounter: number | undefined = undefined; - // Find and remove the matching new note and log(s) if the emitted slottedNoteHash is not empty. - if (!slottedNoteHash.isEmpty()) { + // Find and remove the matching new note and log(s) if the emitted noteHash is not empty. + if (!noteHash.isEmpty()) { const notesInContract = this.noteMap.get(contractAddress.toBigInt()) ?? []; - const noteIndexToRemove = notesInContract.findIndex(n => n.noteHashForConsumption.equals(slottedNoteHash)); + const noteIndexToRemove = notesInContract.findIndex(n => n.noteHashForConsumption.equals(noteHash)); if (noteIndexToRemove === -1) { throw new Error('Attempt to remove a pending note that does not exist.'); } @@ -124,11 +124,11 @@ export class ExecutionNoteCache { * Check if a note exists in the newNotes array. * @param contractAddress - Contract address of the note. * @param storageSlot - Storage slot of the note. - * @param slottedNoteHash - Slotted note hash of the note. + * @param noteHash - A hash of the note. **/ - public checkNoteExists(contractAddress: AztecAddress, slottedNoteHash: Fr) { + public checkNoteExists(contractAddress: AztecAddress, noteHash: Fr) { const notes = this.noteMap.get(contractAddress.toBigInt()) ?? []; - return notes.some(n => n.note.slottedNoteHash.equals(slottedNoteHash)); + return notes.some(n => n.note.noteHash.equals(noteHash)); } /** diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 56a8c254d6f8..d668a2130a3f 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -74,7 +74,7 @@ import { buildL1ToL2Message } from '../test/utils.js'; import { type DBOracle } from './db_oracle.js'; import { CountedPublicExecutionRequest, type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; import { AcirSimulator } from './simulator.js'; -import { computeNoteHidingPoint, computeSlottedNoteHash } from './test_utils.js'; +import { computeNoteHash } from './test_utils.js'; jest.setTimeout(60_000); @@ -321,14 +321,14 @@ describe('Private Execution test suite', () => { const noteHashIndex = randomInt(1); // mock index in TX's final noteHashes array const nonce = computeNoteHashNonce(mockFirstNullifier, noteHashIndex); const note = new Note([new Fr(amount), ownerNpkMHash, Fr.random()]); - const slottedNoteHash = computeSlottedNoteHash(storageSlot, computeNoteHidingPoint(note.items)); + const noteHash = computeNoteHash(storageSlot, note.items); return { contractAddress, storageSlot, noteTypeId, nonce, note, - slottedNoteHash, + noteHash, siloedNullifier: new Fr(0), index: currentNoteIndex++, }; @@ -360,12 +360,7 @@ describe('Private Execution test suite', () => { const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(1); expect(noteHashes[0].value).toEqual( - await acirSimulator.computeSlottedNoteHash( - contractAddress, - newNote.storageSlot, - newNote.noteTypeId, - newNote.note, - ), + await acirSimulator.computeNoteHash(contractAddress, newNote.storageSlot, newNote.noteTypeId, newNote.note), ); const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); @@ -390,12 +385,7 @@ describe('Private Execution test suite', () => { const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(1); expect(noteHashes[0].value).toEqual( - await acirSimulator.computeSlottedNoteHash( - contractAddress, - newNote.storageSlot, - newNote.noteTypeId, - newNote.note, - ), + await acirSimulator.computeNoteHash(contractAddress, newNote.storageSlot, newNote.noteTypeId, newNote.note), ); const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); @@ -448,20 +438,15 @@ describe('Private Execution test suite', () => { expect(recipientNote.storageSlot).toEqual(recipientStorageSlot); expect(recipientNote.noteTypeId).toEqual(valueNoteTypeId); - const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); - expect(noteHashes).toHaveLength(2); - const [changeNoteHash, recipientNoteHash] = noteHashes; - const [recipientSlottedNoteHash, changeSlottedNoteHash] = [ - await acirSimulator.computeSlottedNoteHash( - contractAddress, - recipientStorageSlot, - valueNoteTypeId, - recipientNote.note, - ), - await acirSimulator.computeSlottedNoteHash(contractAddress, storageSlot, valueNoteTypeId, changeNote.note), + const noteHashesFromCallStackItem = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashesFromCallStackItem).toHaveLength(2); + const [changeNoteHashFromCallStackItem, recipientNoteHashFromCallStackItem] = noteHashesFromCallStackItem; + const [changeNoteHash, recipientNoteHash] = [ + await acirSimulator.computeNoteHash(contractAddress, storageSlot, valueNoteTypeId, changeNote.note), + await acirSimulator.computeNoteHash(contractAddress, recipientStorageSlot, valueNoteTypeId, recipientNote.note), ]; - expect(recipientNoteHash.value).toEqual(recipientSlottedNoteHash); - expect(changeNoteHash.value).toEqual(changeSlottedNoteHash); + expect(changeNoteHashFromCallStackItem.value).toEqual(changeNoteHash); + expect(recipientNoteHashFromCallStackItem.value).toEqual(recipientNoteHash); expect(recipientNote.note.items[0]).toEqual(new Fr(amountToTransfer)); expect(changeNote.note.items[0]).toEqual(new Fr(40n)); @@ -471,9 +456,9 @@ describe('Private Execution test suite', () => { const [encryptedChangeLog, encryptedRecipientLog] = newEncryptedLogs; expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); - expect(encryptedChangeLog.noteHashCounter).toEqual(changeNoteHash.counter); + expect(encryptedChangeLog.noteHashCounter).toEqual(changeNoteHashFromCallStackItem.counter); expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[1].log.hash())); - expect(encryptedRecipientLog.noteHashCounter).toEqual(recipientNoteHash.counter); + expect(encryptedRecipientLog.noteHashCounter).toEqual(recipientNoteHashFromCallStackItem.counter); expect(encryptedChangeLog.length.add(encryptedRecipientLog.length)).toEqual( new Fr(getEncryptedNoteSerializedLength(result)), ); @@ -840,7 +825,7 @@ describe('Private Execution test suite', () => { storageSlot, nonce: Fr.ZERO, note, - slottedNoteHash: Fr.ZERO, + noteHash: Fr.ZERO, siloedNullifier: Fr.random(), index: 1n, }, @@ -963,40 +948,40 @@ describe('Private Execution test suite', () => { expect(noteAndSlot.note.items[0]).toEqual(new Fr(amountToTransfer)); - const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); - expect(noteHashes).toHaveLength(1); + const noteHashesFromCallStackItem = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashesFromCallStackItem).toHaveLength(1); - const noteHash = noteHashes[0].value; + const noteHashFromCallStackItem = noteHashesFromCallStackItem[0].value; const storageSlot = deriveStorageSlotInMap( PendingNoteHashesContractArtifact.storageLayout['balances'].slot, owner, ); - const slottedNoteHash = await acirSimulator.computeSlottedNoteHash( + const derivedNoteHash = await acirSimulator.computeNoteHash( contractAddress, storageSlot, valueNoteTypeId, noteAndSlot.note, ); - expect(noteHash).toEqual(slottedNoteHash); + expect(noteHashFromCallStackItem).toEqual(derivedNoteHash); const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.noteHashCounter).toEqual(noteHashes[0].counter); + expect(encryptedLog.noteHashCounter).toEqual(noteHashesFromCallStackItem[0].counter); expect(encryptedLog.noteHashCounter).toEqual(result.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); - // read request should match slottedNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) + // read request should match a note hash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = getNonEmptyItems(result.callStackItem.publicInputs.noteHashReadRequests)[0]; - expect(readRequest.value).toEqual(slottedNoteHash); + expect(readRequest.value).toEqual(derivedNoteHash); expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = result.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2HashWithSeparator( - [slottedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress)], + [derivedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress)], GeneratorIndex.NOTE_NULLIFIER, ); expect(nullifier.value).toEqual(expectedNullifier); @@ -1054,14 +1039,14 @@ describe('Private Execution test suite', () => { const noteHashes = getNonEmptyItems(execInsert.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(1); - const noteHash = noteHashes[0].value; - const slottedNoteHash = await acirSimulator.computeSlottedNoteHash( + const noteHashFromCallStackItem = noteHashes[0].value; + const derivedNoteHash = await acirSimulator.computeNoteHash( contractAddress, noteAndSlot.storageSlot, noteAndSlot.noteTypeId, noteAndSlot.note, ); - expect(noteHash).toEqual(slottedNoteHash); + expect(noteHashFromCallStackItem).toEqual(derivedNoteHash); const newEncryptedLogs = getNonEmptyItems(execInsert.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); @@ -1071,15 +1056,15 @@ describe('Private Execution test suite', () => { expect(encryptedLog.noteHashCounter).toEqual(execInsert.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(execInsert.noteEncryptedLogs[0].log.hash())); - // read request should match slottedNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) + // read request should match a note hash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = execGetThenNullify.callStackItem.publicInputs.noteHashReadRequests[0]; - expect(readRequest.value).toEqual(slottedNoteHash); + expect(readRequest.value).toEqual(derivedNoteHash); expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = execGetThenNullify.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2HashWithSeparator( - [slottedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress)], + [derivedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress)], GeneratorIndex.NOTE_NULLIFIER, ); expect(nullifier.value).toEqual(expectedNullifier); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 53b4ea3b9ee4..601cb2aa6e6f 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -11,7 +11,7 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { type DBOracle } from './db_oracle.js'; import { AcirSimulator } from './simulator.js'; -import { computeNoteHidingPoint, computeSlottedNoteHash } from './test_utils.js'; +import { computeNoteHash } from './test_utils.js'; describe('Simulator', () => { let oracle: MockProxy; @@ -61,9 +61,8 @@ describe('Simulator', () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); const note = createNote(); - const noteHidingPoint = computeNoteHidingPoint(note.items); - const slottedNoteHash = computeSlottedNoteHash(storageSlot, noteHidingPoint); - const uniqueNoteHash = computeUniqueNoteHash(nonce, slottedNoteHash); + const noteHash = computeNoteHash(storageSlot, note.items); + const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash); const siloedNoteHash = siloNoteHash(contractAddress, uniqueNoteHash); const innerNullifier = poseidon2HashWithSeparator( [siloedNoteHash, appNullifierSecretKey], @@ -80,7 +79,7 @@ describe('Simulator', () => { ); expect(result).toEqual({ - slottedNoteHash, + noteHash, uniqueNoteHash, siloedNoteHash, innerNullifier, diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 260282c67a1b..4205fa80b4dc 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -196,7 +196,7 @@ export class AcirSimulator { returnTypes: artifact.returnTypes, }; - const [slottedNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained( + const [noteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained( execRequest, artifact, contractAddress, @@ -204,7 +204,7 @@ export class AcirSimulator { )) as bigint[]; return { - slottedNoteHash: new Fr(slottedNoteHash), + noteHash: new Fr(noteHash), uniqueNoteHash: new Fr(uniqueNoteHash), siloedNoteHash: new Fr(siloedNoteHash), innerNullifier: new Fr(innerNullifier), @@ -212,20 +212,15 @@ export class AcirSimulator { } /** - * Computes the slotted note hash of a note, which contains storage slot and the custom note hash. + * Computes a hash of the note. * @param contractAddress - The address of the contract. * @param storageSlot - The storage slot. * @param noteTypeId - The note type identifier. * @param note - The note. * @returns The note hash. */ - public async computeSlottedNoteHash( - contractAddress: AztecAddress, - storageSlot: Fr, - noteTypeId: NoteSelector, - note: Note, - ) { - const { slottedNoteHash } = await this.computeNoteHashAndOptionallyANullifier( + public async computeNoteHash(contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: NoteSelector, note: Note) { + const { noteHash } = await this.computeNoteHashAndOptionallyANullifier( contractAddress, Fr.ZERO, storageSlot, @@ -233,6 +228,6 @@ export class AcirSimulator { false, note, ); - return slottedNoteHash; + return noteHash; } } diff --git a/yarn-project/simulator/src/client/test_utils.ts b/yarn-project/simulator/src/client/test_utils.ts index f8e34baa86b1..9253a36fcdb0 100644 --- a/yarn-project/simulator/src/client/test_utils.ts +++ b/yarn-project/simulator/src/client/test_utils.ts @@ -11,26 +11,20 @@ const G_SLOT = new Point( /** * Computes a note hiding point as is done by the default implementation injected by macros. + * @param storageSlot - The slot to which the note was inserted. * @param noteContent - The note content (e.g. note.items). - * @returns A note hiding point. + * @returns A note hash. */ -export function computeNoteHidingPoint(noteContent: Fr[]): Point { +export function computeNoteHash(storageSlot: Fr, noteContent: Fr[]): Fr { + // TODO(#7771): update this to do only 1 MSM call const c = pedersenCommit( noteContent.map(f => f.toBuffer()), GeneratorIndex.NOTE_HIDING_POINT, ); - return new Point(new Fr(c[0]), new Fr(c[1]), false); -} + const noteHidingPointBeforeSlotting = new Point(new Fr(c[0]), new Fr(c[1]), false); -/** - * Computes an slotted note hash, given a storage slot and a note hiding point. - * @param storageSlot - The storage slot. - * @param noteHidingPoint - The note hiding point. - * @returns A slotted note hash. - */ -export function computeSlottedNoteHash(storageSlot: Fr, noteHidingPoint: Point): Fr { const grumpkin = new Grumpkin(); - const storageSlotPoint = grumpkin.mul(G_SLOT, new Fq(storageSlot.toBigInt())); - const slottedNoteHidingPoint = grumpkin.add(storageSlotPoint, noteHidingPoint); - return slottedNoteHidingPoint.x; + const slotPoint = grumpkin.mul(G_SLOT, new Fq(storageSlot.toBigInt())); + const noteHidingPoint = grumpkin.add(noteHidingPointBeforeSlotting, slotPoint); + return noteHidingPoint.x; } diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index e446f01d8b56..b1eb64457a8e 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -61,7 +61,7 @@ describe('Unconstrained Execution test suite', () => { nonce: Fr.random(), isSome: new Fr(1), note, - slottedNoteHash: Fr.random(), + noteHash: Fr.random(), siloedNullifier: Fr.random(), index: BigInt(index), })), diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 5b9152982edb..e904db3165bb 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -226,10 +226,10 @@ export class TXE implements TypedOracle { return Promise.resolve(); } - async avmOpcodeEmitNoteHash(slottedNoteHash: Fr) { + async avmOpcodeEmitNoteHash(noteHash: Fr) { const db = this.trees.asLatest(); - const noteHash = siloNoteHash(this.contractAddress, slottedNoteHash); - await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [noteHash]); + const siloedNoteHash = siloNoteHash(this.contractAddress, noteHash); + await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [siloedNoteHash]); return Promise.resolve(); } @@ -253,9 +253,9 @@ export class TXE implements TypedOracle { await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers, NULLIFIER_SUBTREE_HEIGHT); } - async addNoteHashes(contractAddress: AztecAddress, slottedNoteHashes: Fr[]) { + async addNoteHashes(contractAddress: AztecAddress, noteHashes: Fr[]) { const db = this.trees.asLatest(); - const siloedNoteHashes = slottedNoteHashes.map(slottedNoteHash => siloNoteHash(contractAddress, slottedNoteHash)); + const siloedNoteHashes = noteHashes.map(noteHash => siloNoteHash(contractAddress, noteHash)); await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes); } @@ -425,7 +425,7 @@ export class TXE implements TypedOracle { return Promise.resolve(notes); } - notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], slottedNoteHash: Fr, counter: number) { + notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], noteHash: Fr, counter: number) { const note = new Note(noteItems); this.noteCache.addNewNote( { @@ -434,7 +434,7 @@ export class TXE implements TypedOracle { nonce: Fr.ZERO, // Nonce cannot be known during private execution. note, siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note. - slottedNoteHash, + noteHash, }, counter, ); @@ -442,8 +442,8 @@ export class TXE implements TypedOracle { return Promise.resolve(); } - notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, counter: number) { - this.noteCache.nullifyNote(this.contractAddress, innerNullifier, slottedNoteHash); + notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) { + this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash); this.sideEffectsCounter = counter + 1; return Promise.resolve(); } diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 6c107653368d..86985da26e77 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -443,14 +443,14 @@ export class TXEService { storageSlot: ForeignCallSingle, noteTypeId: ForeignCallSingle, note: ForeignCallArray, - slottedNoteHash: ForeignCallSingle, + noteHash: ForeignCallSingle, counter: ForeignCallSingle, ) { this.typedOracle.notifyCreatedNote( fromSingle(storageSlot), NoteSelector.fromField(fromSingle(noteTypeId)), fromArray(note), - fromSingle(slottedNoteHash), + fromSingle(noteHash), fromSingle(counter).toNumber(), ); return toForeignCallResult([toSingle(new Fr(0))]); @@ -458,12 +458,12 @@ export class TXEService { async notifyNullifiedNote( innerNullifier: ForeignCallSingle, - slottedNoteHash: ForeignCallSingle, + noteHash: ForeignCallSingle, counter: ForeignCallSingle, ) { await this.typedOracle.notifyNullifiedNote( fromSingle(innerNullifier), - fromSingle(slottedNoteHash), + fromSingle(noteHash), fromSingle(counter).toNumber(), ); return toForeignCallResult([toSingle(new Fr(0))]); @@ -512,8 +512,8 @@ export class TXEService { return toForeignCallResult([]); } - async avmOpcodeEmitNoteHash(slottedNoteHash: ForeignCallSingle) { - await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(slottedNoteHash)); + async avmOpcodeEmitNoteHash(noteHash: ForeignCallSingle) { + await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(noteHash)); return toForeignCallResult([]); }