Skip to content

Commit

Permalink
refactor: split note content hashing in two
Browse files Browse the repository at this point in the history
  • Loading branch information
alexghr committed Mar 4, 2024
1 parent de60af6 commit 14e4824
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 35 deletions.
6 changes: 5 additions & 1 deletion noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ impl NoteInterface<ADDRESS_NOTE_LEN> for AddressNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn compute_nullifier(self, context: &mut PrivateContext) -> Field {
let note_hash_for_nullify = compute_note_hash_for_consumption(self);
let secret = context.request_nullifier_secret_key(self.owner);
Expand Down
5 changes: 3 additions & 2 deletions noir-projects/aztec-nr/aztec/src/note/note_interface.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ trait NoteInterface<N> {

fn deserialize_content(fields: [Field; N]) -> Self;

fn compute_note_content_hash(self) -> Field;
fn compute_inner_note_content_hash(self) -> Field;

fn compute_outer_note_content_hash(self) -> Field;

fn get_header(self) -> NoteHeader;

Expand All @@ -22,4 +24,3 @@ trait NoteInterface<N> {
fn get_note_type_id() -> Field;
}
// docs:end:note_interface

11 changes: 9 additions & 2 deletions noir-projects/aztec-nr/aztec/src/note/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ fn compute_unique_hash(nonce: Field, siloed_note_hash: Field) -> Field {
pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)
}

fn compute_partial_note_hash<Note, N>(note: Note) -> Field where Note: NoteInterface<N> {
let header = note.get_header();
let inner_content_hash = note.compute_inner_note_content_hash();
pedersen_hash([header.storage_slot, inner_content_hash], 0)
}

fn compute_non_siloed_note_hash<Note, N>(note: Note) -> Field where Note: NoteInterface<N> {
let header = note.get_header();
let note_hash = note.compute_note_content_hash();
let partial_note_hash = compute_partial_note_hash(note);
let outer_content_hash = note.compute_outer_note_content_hash();

// TODO(#1205) Do we need a generator index here?
pedersen_hash([header.storage_slot, note_hash], 0)
pedersen_hash([partial_note_hash, outer_content_hash], 0)
}

fn compute_siloed_note_hash<Note, N>(note_with_header: Note) -> Field where Note: NoteInterface<N> {
Expand Down
6 changes: 5 additions & 1 deletion noir-projects/aztec-nr/field-note/src/field_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ impl NoteInterface<FIELD_NOTE_LEN> for FieldNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn compute_nullifier(self, _context: &mut PrivateContext) -> Field {
// This note is expected to be shared between users and for this reason can't be nullified using a secret.
0
Expand Down
8 changes: 6 additions & 2 deletions noir-projects/aztec-nr/value-note/src/value_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ impl NoteInterface<VALUE_NOTE_LEN> for ValueNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(),0)
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

// docs:start:nullifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,16 @@ impl NoteInterface<SUBSCRIPTION_NOTE_LEN> for SubscriptionNote {
],0)
}

fn compute_note_content_hash(note: SubscriptionNote) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(note.serialize_content(), 0)
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}


fn set_header(&mut self, header: NoteHeader) {
self.header = header;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ impl NoteInterface<CARD_NOTE_LEN> for CardNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn compute_nullifier(self, context: &mut PrivateContext) -> Field {
let note_hash_for_nullify = compute_note_hash_for_consumption(self);
let secret = context.request_nullifier_secret_key(self.owner);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl NoteInterface<ECDSA_PUBLIC_KEY_NOTE_LEN> for EcdsaPublicKeyNote {

let last_x = self.x[31] as Field;
let last_y = self.y[31] as Field;

[x, last_x, y, last_y, self.owner.to_field()]
}

Expand All @@ -61,9 +61,13 @@ impl NoteInterface<ECDSA_PUBLIC_KEY_NOTE_LEN> for EcdsaPublicKeyNote {
EcdsaPublicKeyNote { x, y, owner: AztecAddress::from_field(serialized_note[4]), header: NoteHeader::empty() }
}

fn compute_note_content_hash(note: EcdsaPublicKeyNote) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(note.serialize_content(), 0)
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn compute_nullifier(self, context: &mut PrivateContext) -> Field {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ impl NoteInterface<PUBLIC_KEY_NOTE_LEN> for PublicKeyNote {
],0)
}

fn compute_note_content_hash(note: PublicKeyNote) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(note.serialize_content(), 0)
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn set_header(&mut self, header: NoteHeader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header.
struct TokenNote {
// the amount of tokens in the note
amount: U128,
// the provider of secrets for the nullifier. The owner (recipient) to ensure that the note
// can be privately spent. When nullifier secret and encryption private key is same
// the provider of secrets for the nullifier. The owner (recipient) to ensure that the note
// can be privately spent. When nullifier secret and encryption private key is same
// we can simply use the owner for this one.
owner: AztecAddress,
// randomness of the note to hide contents.
Expand All @@ -43,11 +43,15 @@ impl NoteInterface<TOKEN_NOTE_LEN> for TokenNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

// docs:start:nullifier
fn compute_nullifier(self, context: &mut PrivateContext) -> Field {
let note_hash_for_nullify = compute_note_hash_for_consumption(self);
Expand Down Expand Up @@ -120,5 +124,5 @@ impl OwnedNote for TokenNote {
fn get_owner(self) -> AztecAddress {
self.owner
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

fn compute_nullifier(self, _context: &mut PrivateContext) -> Field {
self.compute_nullifier_without_context()
}
Expand Down Expand Up @@ -86,4 +90,4 @@ impl TransparentNote {
assert(self.secret_hash == hash);
}
}
// docs:end:token_types_all
// docs:end:token_types_all
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header.
struct TokenNote {
// the amount of tokens in the note
amount: U128,
// the provider of secrets for the nullifier. The owner (recipient) to ensure that the note
// can be privately spent. When nullifier secret and encryption private key is same
// the provider of secrets for the nullifier. The owner (recipient) to ensure that the note
// can be privately spent. When nullifier secret and encryption private key is same
// we can simply use the owner for this one.
owner: AztecAddress,
// randomness of the note to hide contents.
Expand All @@ -43,11 +43,15 @@ impl NoteInterface<TOKEN_NOTE_LEN> for TokenNote {
}
}

fn compute_note_content_hash(self) -> Field {
fn compute_inner_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}

// docs:start:nullifier
fn compute_nullifier(self, context: &mut PrivateContext) -> Field {
let note_hash_for_nullify = compute_note_hash_for_consumption(self);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ struct TransparentNote {
}

impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
fn compute_inner_note_content_hash(self) -> Field {
pedersen_hash(self.serialize_content(), 0)
}

fn compute_outer_note_content_hash(self) -> Field {
0
}
fn serialize_content(self) -> [Field; TRANSPARENT_NOTE_LEN] {
[self.amount, self.secret_hash]
}
Expand All @@ -31,11 +38,6 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
}
}

fn compute_note_content_hash(self) -> Field {
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash(self.serialize_content(), 0)
}

fn compute_nullifier(self, _context: &mut PrivateContext) -> Field {
self.compute_nullifier_without_context()
}
Expand Down Expand Up @@ -86,4 +88,4 @@ impl TransparentNote {
assert(self.secret_hash == hash);
}
}
// docs:end:token_types_all
// docs:end:token_types_all
6 changes: 4 additions & 2 deletions yarn-project/simulator/src/client/simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ describe('Simulator', () => {
oracle.getFunctionArtifactByName.mockResolvedValue(artifact);

const note = createNote();
const tokenNoteHash = hashFields(note.items);
const nonSiloedNoteHash = hashFields([storageSlot, tokenNoteHash]);
const tokenNoteInnerHash = hashFields([note.items[0], note.items[1], note.items[2]]);
const tokenNoteOuterHash = Fr.ZERO;
const partialNoteHash = hashFields([storageSlot, tokenNoteInnerHash]);
const nonSiloedNoteHash = hashFields([partialNoteHash, tokenNoteOuterHash]);
const siloedNoteHash = siloNoteHash(contractAddress, nonSiloedNoteHash);
const uniqueSiloedNoteHash = computeUniqueCommitment(nonce, siloedNoteHash);
const nonSiloedNullifier = hashFields([
Expand Down
8 changes: 6 additions & 2 deletions yarn-project/simulator/src/public/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,13 @@ describe('ACIR public execution simulator', () => {
// Assert the note hash was created
expect(result.newNoteHashes.length).toEqual(1);

const expectedNoteHash = pedersenHash([amount.toBuffer(), secretHash.toBuffer()]);
const expectedInnerNoteContentHash = pedersenHash([amount.toBuffer(), secretHash.toBuffer()]);
const expectedOuterNoteContentHash = Fr.ZERO;
const storageSlot = new Fr(5); // for pending_shields
const expectedNonSiloedNoteHash = pedersenHash([storageSlot, expectedNoteHash].map(f => f.toBuffer()));
const expectedNonSiloedNoteHash = pedersenHash([
pedersenHash([storageSlot, expectedInnerNoteContentHash].map(f => f.toBuffer())).toBuffer(),
expectedOuterNoteContentHash.toBuffer(),
]);
expect(result.newNoteHashes[0].value).toEqual(expectedNonSiloedNoteHash);
});

Expand Down

0 comments on commit 14e4824

Please sign in to comment.