diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 49311d794af5..c5c06b46bcbf 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -2,7 +2,10 @@ use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interf use dep::protocol_types::{ address::AztecAddress, - constants::{GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__SILOED_NOTE_HASH}, + constants::{ + GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, + GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__INNER_NOTE_HASH +}, hash::pedersen_hash, utils::arr_copy_slice }; @@ -20,8 +23,10 @@ fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterfa let header = note.get_header(); let note_hash = note.compute_note_content_hash(); - // TODO(#1205) Do we need a generator index here? - pedersen_hash([header.storage_slot, note_hash], 0) + pedersen_hash( + [header.storage_slot, note_hash], + GENERATOR_INDEX__INNER_NOTE_HASH + ) } fn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index d5cf7197cef6..9fc1d0737fc5 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, }; global TRANSPARENT_NOTE_LEN: Field = 2; 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 ba07e8518b1a..10649ef22cf3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -243,3 +243,5 @@ global GENERATOR_INDEX__OVSK_M = 49; global GENERATOR_INDEX__TSK_M = 50; global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51; global GENERATOR_INDEX__NOTE_NULLIFIER = 52; +global GENERATOR_INDEX__INNER_NOTE_HASH = 53; +global GENERATOR_INDEX__NOTE_CONTENT_HASH = 54; 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 4b72759a5dba..a5920568be43 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -414,8 +414,7 @@ fn generate_note_properties_fn( // Automatically generate the method to compute the note's content hash as: // fn compute_note_content_hash(self: NoteType) -> Field { -// // TODO(#1205) Should use a non-zero generator index. -// dep::aztec::hash::pedersen_hash(self.serialize_content(), 0) +// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) // } // fn generate_compute_note_content_hash( @@ -425,8 +424,7 @@ fn generate_compute_note_content_hash( let function_source = format!( " fn compute_note_content_hash(self: {}) -> Field {{ - // TODO(#1205) Should use a non-zero generator index. - dep::aztec::hash::pedersen_hash(self.serialize_content(), 0) + dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) }} ", note_type diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index c40cdec3ec51..f141aa310705 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -203,4 +203,6 @@ export enum GeneratorIndex { TSK_M = 50, PUBLIC_KEYS_HASH = 51, NOTE_NULLIFIER = 52, + INNER_NOTE_HASH = 53, + NOTE_CONTENT_HASH = 54, } diff --git a/yarn-project/circuits.js/src/hash/hash.test.ts b/yarn-project/circuits.js/src/hash/hash.test.ts index cb1cd8626619..477990a388b4 100644 --- a/yarn-project/circuits.js/src/hash/hash.test.ts +++ b/yarn-project/circuits.js/src/hash/hash.test.ts @@ -10,7 +10,7 @@ import { computePublicDataTreeLeafSlot, computePublicDataTreeValue, computeSecretHash, - computeUniqueCommitment, + computeUniqueNoteHash, computeVarArgsHash, hashVK, siloNoteHash, @@ -35,7 +35,7 @@ describe('hash', () => { it('computes unique commitment', () => { const nonce = new Fr(123n); const innerCommitment = new Fr(456); - const res = computeUniqueCommitment(nonce, innerCommitment); + const res = computeUniqueNoteHash(nonce, innerCommitment); expect(res).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/hash/hash.ts b/yarn-project/circuits.js/src/hash/hash.ts index 94998bf7ee3c..7f3d489b7ba3 100644 --- a/yarn-project/circuits.js/src/hash/hash.ts +++ b/yarn-project/circuits.js/src/hash/hash.ts @@ -76,13 +76,33 @@ export function siloNoteHash(contract: AztecAddress, innerNoteHash: Fr): Fr { } /** - * Computes a unique commitment. It includes a nonce which contains data that guarantees the commitment will be unique. + * Computes a note content hash. + * @param noteContent - The note content (e.g. note.items). + * @returns A note content hash. + */ +export function computeNoteContentHash(noteContent: Fr[]): Fr { + return pedersenHash(noteContent, GeneratorIndex.NOTE_CONTENT_HASH); +} + +/** + * Computes an inner note hash, given a storage slot and a note hash. + * @param storageSlot - The storage slot. + * @param noteHash - The note hash. + * @returns An inner note hash. + */ +export function computeInnerNoteHash(storageSlot: Fr, noteHash: Fr): Fr { + return pedersenHash([storageSlot, noteHash], GeneratorIndex.INNER_NOTE_HASH); +} + +/** + * Computes a unique note hash. + * @dev Includes a nonce which contains data that guarantees the resulting note hash will be unique. * @param nonce - The contract address. - * @param siloedCommitment - An siloed commitment. - * @returns A unique commitment. + * @param siloedNoteHash - An siloed note hash. + * @returns A unique note hash. */ -export function computeUniqueCommitment(nonce: Fr, siloedCommitment: Fr): Fr { - return pedersenHash([nonce, siloedCommitment], GeneratorIndex.UNIQUE_NOTE_HASH); +export function computeUniqueNoteHash(nonce: Fr, siloedNoteHash: Fr): Fr { + return pedersenHash([nonce, siloedNoteHash], GeneratorIndex.UNIQUE_NOTE_HASH); } /** diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 88720fba6f86..0ec755281ccb 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -22,7 +22,7 @@ import { type TxContext, } from '@aztec/circuits.js'; import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; -import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; +import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, type Point } from '@aztec/foundation/fields'; @@ -257,7 +257,7 @@ export class ClientExecutionContext extends ViewDataOracle { notes.forEach(n => { if (n.index !== undefined) { const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash); - const uniqueSiloedNoteHash = computeUniqueCommitment(n.nonce, siloedNoteHash); + const uniqueSiloedNoteHash = computeUniqueNoteHash(n.nonce, siloedNoteHash); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) // Should always be uniqueSiloedNoteHash when publicly created notes include nonces. const noteHashForReadRequest = n.nonce.isZero() ? siloedNoteHash : uniqueSiloedNoteHash; diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 87ca2ef7fc4e..e4af77f494bd 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,6 +1,6 @@ import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; import { GeneratorIndex, computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; -import { computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; +import { computeInnerNoteHash, computeNoteContentHash, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { ABIParameterVisibility, type FunctionArtifactWithDebugMetadata, @@ -63,10 +63,10 @@ describe('Simulator', () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); const note = createNote(); - const tokenNoteHash = pedersenHash(note.items); - const innerNoteHash = pedersenHash([storageSlot, tokenNoteHash]); + const tokenNoteHash = computeNoteContentHash(note.items); + const innerNoteHash = computeInnerNoteHash(storageSlot, tokenNoteHash); const siloedNoteHash = siloNoteHash(contractAddress, innerNoteHash); - const uniqueSiloedNoteHash = computeUniqueCommitment(nonce, siloedNoteHash); + const uniqueSiloedNoteHash = computeUniqueNoteHash(nonce, siloedNoteHash); const innerNullifier = poseidon2Hash([ uniqueSiloedNoteHash, appNullifierSecretKey, diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 04568e3a46ac..886ebf355fb6 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -12,7 +12,7 @@ import { NullifierLeaf, NullifierLeafPreimage, } from '@aztec/circuits.js'; -import { siloNullifier } from '@aztec/circuits.js/hash'; +import { computeInnerNoteHash, computeNoteContentHash, siloNullifier } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; import { type FunctionArtifact, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; @@ -334,9 +334,9 @@ describe('ACIR public execution simulator', () => { // Assert the note hash was created expect(result.newNoteHashes.length).toEqual(1); - const expectedNoteHash = pedersenHash([amount, secretHash]); + const expectedNoteHash = computeNoteContentHash([amount, secretHash]); const storageSlot = new Fr(5); // for pending_shields - const expectedInnerNoteHash = pedersenHash([storageSlot, expectedNoteHash]); + const expectedInnerNoteHash = computeInnerNoteHash(storageSlot, expectedNoteHash); expect(result.newNoteHashes[0].value).toEqual(expectedInnerNoteHash); });