Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/aztec/smart_contracts/functions/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl NoteHash for CustomNote {
)
}

unconstrained fn compute_nullifier_without_context(self, storage_slot: Field, contract_address: AztecAddress, note_nonce: Field) -> Field {
unconstrained fn compute_nullifier_unconstrained(self, storage_slot: Field, contract_address: AztecAddress, note_nonce: Field) -> Field {
// We set the note_hash_counter to 0 as the note is not transient and the concept of transient note does
// not make sense in an unconstrained context.
let retrieved_note = RetrievedNote { note: self, contract_address, nonce: note_nonce, note_hash_counter: 0 };
Expand Down
13 changes: 13 additions & 0 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ Aztec is in full-speed development. Literally every version breaks compatibility

## TBD

### [aztec-nr] `compute_nullifier_without_context` renamed

The `compute_nullifier_without_context` function from `NoteHash` (ex `NoteInterface`) is now called `compute_nullifier_unconstrained`, and instead of taking storage slot, contract address and nonce it takes a note hash for nullification (same as `compute_note_hash`). This makes writing this
function simpler:

```diff
- unconstrained fn compute_nullifier_without_context(self, storage_slot: Field, contract_address: AztecAddress, nonce: Field) -> Field {
- let note_hash_for_nullify = ...;
+ unconstrained fn compute_nullifier_unconstrained(self, note_hash_for_nullify: Field) -> Field {
...
}
```

### `U128` type replaced with native `u128`

The `U128` type has been replaced with the native `u128` type. This means that you can no longer use the `U128` type in your code. Instead, you should use the `u128` type.
Expand Down
9 changes: 7 additions & 2 deletions noir-projects/aztec-nr/aztec/src/discovery/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub global MAX_NOTE_PACKED_LEN: u32 = PRIVATE_LOG_SIZE_IN_FIELDS - NOTE_PRIVATE_
pub struct NoteHashAndNullifier {
/// The result of NoteHash::compute_note_hash
pub note_hash: Field,
/// The result of NullifiableNote::compute_nullifier_without_context
/// The result of NoteHash::compute_nullifier_unconstrained (since all of note discovery is unconstrained)
pub inner_nullifier: Field,
}

Expand All @@ -39,7 +39,12 @@ pub struct NoteHashAndNullifier {
/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));
///
/// let note_hash = note.compute_note_hash(storage_slot);
/// let inner_nullifier = note.compute_nullifier_without_context(storage_slot, contract_address, nonce);
/// let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(
/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(nonce).into() },
/// storage_slot
/// );
///
/// let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);
///
/// Option::some(
/// aztec::discovery::NoteHashAndNullifier {
Expand Down
29 changes: 27 additions & 2 deletions noir-projects/aztec-nr/aztec/src/macros/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ comptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -
quote { unpack },
);

let compute_note_hash = get_trait_impl_method(
typ,
quote { crate::note::note_interface::NoteHash },
quote { compute_note_hash },
);

let compute_nullifier_unconstrained = get_trait_impl_method(
typ,
quote { crate::note::note_interface::NoteHash },
quote { compute_nullifier_unconstrained },
);

let if_or_else_if = if i == 0 {
quote { if }
} else {
Expand All @@ -177,8 +189,21 @@ comptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -

let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));

let note_hash = note.compute_note_hash(storage_slot);
let inner_nullifier = note.compute_nullifier_without_context(storage_slot, contract_address, nonce);
let note_hash = $compute_note_hash(note, storage_slot);

// The note discovery process finds settled notes, that is, notes that were created in prior
// transactions and are therefore already part of the note hash tree. We therefore compute the
// nullification note hash by treating the note as a settled note with the provided nonce.
let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(
aztec::note::retrieved_note::RetrievedNote{
note,
contract_address,
metadata: aztec::note::note_metadata::SettledNoteMetadata::new(nonce).into()
},
storage_slot,
);

let inner_nullifier = $compute_nullifier_unconstrained(note, note_hash_for_nullify);

Option::some(
aztec::discovery::NoteHashAndNullifier {
Expand Down
42 changes: 7 additions & 35 deletions noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,7 @@ comptime fn generate_note_interface(s: StructDefinition, note_type_id: Field) ->
///
/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { ... }
///
/// unconstrained fn compute_nullifier_without_context(
/// self,
/// storage_slot: Field,
/// contract_address: AztecAddress,
/// note_nonce: Field,
/// ) -> Field { ... }
/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullify: Field) -> Field { ... }
/// }
/// ```
comptime fn generate_note_hash_trait_impl(s: StructDefinition) -> Quoted {
Expand Down Expand Up @@ -112,18 +107,10 @@ comptime fn generate_note_hash_trait_impl(s: StructDefinition) -> Quoted {
)
}

unconstrained fn compute_nullifier_without_context(
unconstrained fn compute_nullifier_unconstrained(
self,
storage_slot: Field,
contract_address: aztec::prelude::AztecAddress,
note_nonce: Field,
note_hash_for_nullify: Field,
) -> Field {
let retrieved_note = aztec::prelude::RetrievedNote {
note: self,
contract_address,
metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into(),
};
let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(retrieved_note, storage_slot);
let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;
// We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly
// in the quote to avoid "trait not in scope" compiler warnings.
Expand All @@ -149,14 +136,7 @@ comptime fn generate_note_hash_trait_impl(s: StructDefinition) -> Quoted {
/// ...
/// }
///
/// unconstrained fn compute_nullifier_without_context(
/// self,
/// storage_slot: Field,
/// contract_address: AztecAddress,
/// note_nonce: Field,
/// ) -> Field {
/// ...
/// }
/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullify: Field) -> Field { ... }
/// }
///
/// # On differences from `generate_note_hash_trait_impl`
Expand Down Expand Up @@ -230,18 +210,10 @@ comptime fn generate_note_hash_trait_impl_for_partial_note(
)
}

unconstrained fn compute_nullifier_without_context(
unconstrained fn compute_nullifier_unconstrained(
self,
storage_slot: Field,
contract_address: aztec::prelude::AztecAddress,
note_nonce: Field,
note_hash_for_nullify: Field,
) -> Field {
let retrieved_note = aztec::prelude::RetrievedNote {
note: self,
contract_address,
metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into(),
};
let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(retrieved_note, storage_slot);
let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;
// We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly in
// the quote to avoid "trait not in scope" compiler warnings.
Expand Down Expand Up @@ -1127,7 +1099,7 @@ pub comptime fn note(s: StructDefinition) -> Quoted {
///
/// // Custom nullifier computation...
/// fn compute_nullifier(...) -> Field { ... }
/// fn compute_nullifier_without_context(...) -> Field { ... }
/// fn compute_nullifier_unconstrained(...) -> Field { ... }
/// }
/// ```
pub comptime fn custom_note(s: StructDefinition) -> Quoted {
Expand Down
21 changes: 4 additions & 17 deletions noir-projects/aztec-nr/aztec/src/note/note_interface.nr
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,10 @@ pub trait NoteHash {
/// circuits.
fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field;

/// Like `compute_nullifier`, this function also computes a note's nullifier, but there are some key differences.
///
/// First and most importantly, this function is unconstrained: there are no guarantees on the returned value being
/// correct. Because of that it doesn't need to take a context (since it won't perform any kernel key validation
/// requests).
///
/// Second, it always computes the nullifier for a **settled** note, i.e. a note that has been created in a previous
/// transaction, which therefore has a nonce. This is typically fine, since this function will mostly be used in
/// unconstrained execution contexts, which exist outside of any transaction and therefore have no concept of
/// pending notes, only settled. This also causes this function to not need to take a note hash for nullification,
/// since it will just compute the unique note hash internally using the provided nonce.
unconstrained fn compute_nullifier_without_context(
self,
storage_slot: Field,
contract_address: AztecAddress,
note_nonce: Field,
) -> Field;
/// Like `compute_nullifier`, except this variant is unconstrained: there are no guarantees on the returned value
/// being correct. Because of that it doesn't need to take a context (since it won't perform any kernel key
/// validation requests).
unconstrained fn compute_nullifier_unconstrained(self, note_hash_for_nullify: Field) -> Field;
}
// docs:end:note_interfaces

Expand Down
3 changes: 2 additions & 1 deletion noir-projects/aztec-nr/aztec/src/note/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ where
}
}

/// Returns the note hash that must be used to compute a note's nullifier.
/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or
/// `NoteHash::compute_nullifier_unconstrained`.
pub fn compute_note_hash_for_nullify<Note>(
retrieved_note: RetrievedNote<Note>,
storage_slot: Field,
Expand Down
20 changes: 2 additions & 18 deletions noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use crate::{
context::PrivateContext,
note::{
note_interface::{NoteHash, NoteType},
note_metadata::SettledNoteMetadata,
retrieved_note::RetrievedNote,
utils::compute_note_hash_for_nullify,
},
note::{note_interface::{NoteHash, NoteType}, retrieved_note::RetrievedNote},
};

use dep::protocol_types::{
Expand Down Expand Up @@ -47,20 +42,9 @@ impl NoteHash for MockNote {
)
}

unconstrained fn compute_nullifier_without_context(
self,
storage_slot: Field,
contract_address: AztecAddress,
note_nonce: Field,
) -> Field {
let retrieved_note = RetrievedNote {
note: self,
contract_address,
metadata: SettledNoteMetadata::new(note_nonce).into(),
};
unconstrained fn compute_nullifier_unconstrained(self, note_hash_for_nullify: Field) -> Field {
// We don't use any kind of secret here since this is only a mock note and having it here would make tests
// more cumbersome
let note_hash_for_nullify = compute_note_hash_for_nullify(retrieved_note, storage_slot);
poseidon2_hash_with_separator(
[note_hash_for_nullify],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use dep::aztec::{
macros::notes::custom_note,
note::note_interface::NoteHash,
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_HASH,
hash::poseidon2_hash_with_separator, traits::Packable, utils::arrays::array_concat,
constants::GENERATOR_INDEX__NOTE_HASH, hash::poseidon2_hash_with_separator,
traits::Packable, utils::arrays::array_concat,
},
};

Expand All @@ -27,17 +27,17 @@ impl NoteHash for TestNote {
_context: &mut PrivateContext,
_note_hash_for_nullify: Field,
) -> Field {
// This note is never nullified so we don't care about having a real implementation here.
// This note's nullifier is never used for any meaningful purpose so we don't care about having a real
// implementation here.
0
}

unconstrained fn compute_nullifier_without_context(
unconstrained fn compute_nullifier_unconstrained(
_self: Self,
_storage_slot: Field,
_contract_address: AztecAddress,
_note_nonce: Field,
_note_hash_for_nullify: Field,
) -> Field {
// This note is never nullified so we don't care about having a real implementation here.
// This note's nullifier is never used for any meaningful purpose so we don't care about having a real
// implementation here.
0
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use dep::aztec::{
macros::notes::custom_note,
note::{note_metadata::SettledNoteMetadata, utils::compute_note_hash_for_nullify},
prelude::{NoteHash, PrivateContext, RetrievedNote},
prelude::{NoteHash, PrivateContext},
protocol_types::{
address::AztecAddress,
constants::{GENERATOR_INDEX__NOTE_HASH, GENERATOR_INDEX__NOTE_NULLIFIER},
hash::poseidon2_hash_with_separator,
traits::Packable,
Expand Down Expand Up @@ -48,18 +46,7 @@ impl NoteHash for TransparentNote {
)
}

unconstrained fn compute_nullifier_without_context(
self,
storage_slot: Field,
contract_address: AztecAddress,
note_nonce: Field,
) -> Field {
let retrieved_note = RetrievedNote {
note: self,
contract_address,
metadata: SettledNoteMetadata::new(note_nonce).into(),
};
let note_hash_for_nullify = compute_note_hash_for_nullify(retrieved_note, storage_slot);
unconstrained fn compute_nullifier_unconstrained(self, note_hash_for_nullify: Field) -> Field {
// compute_nullifier ignores context so we can reuse it here
self.compute_nullifier(zeroed(), note_hash_for_nullify)
}
Expand Down
Loading