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
35 changes: 22 additions & 13 deletions noir-projects/aztec-nr/aztec/src/note/note_getter.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::note::{
utils::compute_note_hash_for_read_request,
};
use crate::oracle;
use crate::utils::comparison::compare;
use crate::utils::{array, comparison::compare};
use dep::protocol_types::{
constants::{GET_NOTES_ORACLE_RETURN_LENGTH, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL},
traits::{Packable, ToField},
Expand Down Expand Up @@ -99,6 +99,14 @@ where
(retrieved_note, note_hash_for_read_request)
}

/// Returns a BoundedVec of notes that have been proven to have been created by this contract, either in the current or
/// past transactions (i.e. pending or settled notes). A second BoundedVec contains the note hashes used for the read
/// requests, which can save constraints when computing the note's nullifiers.
///
/// WARNING: recall that notes are never destroyed! Note existence therefore does not imply that the note is _current_
/// or _valid_ - this typically requires also emitting the note's nullifier to prove that it had not been emitted
/// before. Because of this, calling this function directly from end-user applications should be discouraged, and safe
/// abstractions such as aztec-nr's state variables should be used instead.
pub fn get_notes<Note, let N: u32, PREPROCESSOR_ARGS, FILTER_ARGS>(
context: &mut PrivateContext,
storage_slot: Field,
Expand Down Expand Up @@ -140,7 +148,7 @@ where
let filter_args = options.filter_args;
let filtered_notes = filter_fn(opt_notes, filter_args);

let notes = crate::utils::array::collapse(filtered_notes);
let notes = array::collapse(filtered_notes);
let mut note_hashes = BoundedVec::new();

// We have now collapsed the sparse array of Options into a BoundedVec. This is a more ergonomic type and also
Expand Down Expand Up @@ -239,18 +247,22 @@ where
apply_preprocessor(opt_notes, options.preprocessor, options.preprocessor_args)
}

/// Unconstrained variant of `get_notes`, meant to be used in unconstrained execution contexts. Notably only the note
/// content is returned, and not any of the information used when proving its existence (e.g. nonce, note hash, etc.).
pub unconstrained fn view_notes<Note, let N: u32>(
storage_slot: Field,
options: NoteViewerOptions<Note, N>,
) -> BoundedVec<Note, MAX_NOTES_PER_PAGE>
where
Note: NoteType + Packable<N>,
Note: NoteType + Packable<N> + Eq,
{
let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) =
flatten_options(options.selects, options.sorts);
let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];

let notes_array: [_; MAX_NOTES_PER_PAGE] = oracle::notes::get_notes(
// We fetch the notes from the same oracle we use in the constrained case, except we don't bother inspecting the
// metadata in order to prove existence.
let opt_notes = oracle::notes::get_notes(
storage_slot,
num_selects,
select_by_indexes,
Expand All @@ -268,15 +280,12 @@ where
placeholder_fields,
);

let mut notes = BoundedVec::new();
for i in 0..notes_array.len() {
if notes_array[i].is_some() {
// We're not constraining note existence so we just drop the metadata
notes.push(notes_array[i].unwrap_unchecked().note);
}
}

notes
// Even though we don't expect for the opt_notes array to be sparse, collapse is still useful in this case to
// convert it into a BoundedVec.
array::collapse(opt_notes).map(
// view_notes just returns the actual note, so we drop the metadata
|retrieved_note| retrieved_note.note,
)
}

unconstrained fn flatten_options<let N: u32>(
Expand Down
10 changes: 5 additions & 5 deletions noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ impl<Note> PrivateImmutable<Note, &mut PrivateContext> {
// docs:end:get_note
}

impl<Note> PrivateImmutable<Note, UnconstrainedContext> {
impl<Note, let N: u32> PrivateImmutable<Note, UnconstrainedContext>
where
Note: NoteType + NoteHash + Packable<N> + Eq,
{
// docs:start:is_initialized
pub unconstrained fn is_initialized(self) -> bool {
let nullifier = self.compute_initialization_nullifier();
Expand All @@ -92,10 +95,7 @@ impl<Note> PrivateImmutable<Note, UnconstrainedContext> {

// view_note does not actually use the context, but it calls oracles that are only available in private
// docs:start:view_note
pub unconstrained fn view_note<let N: u32>(self) -> Note
where
Note: NoteType + NoteHash + Packable<N>,
{
pub unconstrained fn view_note(self) -> Note {
let mut options = NoteViewerOptions::new();
view_notes(self.storage_slot, options.set_limit(1)).get(0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ where

impl<Note, let N: u32> PrivateMutable<Note, UnconstrainedContext>
where
Note: NoteType + NoteHash + Packable<N>,
Note: NoteType + NoteHash + Packable<N> + Eq,
{
pub unconstrained fn is_initialized(self) -> bool {
let nullifier = self.compute_initialization_nullifier();
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ where

impl<Note, let N: u32> PrivateSet<Note, UnconstrainedContext>
where
Note: NoteType + NoteHash + Packable<N>,
Note: NoteType + NoteHash + Packable<N> + Eq,
{
// docs:start:view_notes
pub unconstrained fn view_notes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use dep::aztec::{
};

#[note]
#[derive(Eq)]
pub struct SubscriptionNote {
owner: AztecAddress,
expiry_block_number: Field,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use aztec::{macros::notes::note, protocol_types::address::AztecAddress};
// Stores a public key composed of two fields
// TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value?
#[note]
#[derive(Eq)]
pub struct PublicKeyNote {
x: Field,
y: Field,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,15 @@ impl<Note, Context> BalanceSet<Note, Context> {
}
}

impl<Note> BalanceSet<Note, UnconstrainedContext> {
pub unconstrained fn balance_of<let N: u32>(self: Self) -> u128
where
Note: NoteType + NoteHash + OwnedNote + Packable<N>,
{
impl<Note> BalanceSet<Note, UnconstrainedContext>
where
Note: NoteType + NoteHash + OwnedNote + Packable<N> + Eq,
{
pub unconstrained fn balance_of<let N: u32>(self: Self) -> u128 {
self.balance_of_with_offset(0)
}

pub unconstrained fn balance_of_with_offset<let N: u32>(self: Self, offset: u32) -> u128
where
Note: NoteType + NoteHash + OwnedNote + Packable<N>,
{
pub unconstrained fn balance_of_with_offset<let N: u32>(self: Self, offset: u32) -> u128 {
let mut balance = 0 as u128;
// docs:start:view_notes
let mut options = NoteViewerOptions::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use dep::aztec::{

/// A note used only for testing purposes.
#[custom_note]
#[derive(Eq)]
pub struct TestNote {
value: Field,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,19 @@ impl<Note, Context> BalancesMap<Note, Context> {
}
}

impl<Note> BalancesMap<Note, UnconstrainedContext> {
pub unconstrained fn balance_of<let N: u32>(self: Self, owner: AztecAddress) -> u128
where
Note: NoteType + NoteHash + OwnedNote + Packable<N>,
{
impl<Note> BalancesMap<Note, UnconstrainedContext>
where
Note: NoteType + NoteHash + OwnedNote + Packable<N> + Eq,
{
pub unconstrained fn balance_of<let N: u32>(self: Self, owner: AztecAddress) -> u128 {
self.balance_of_with_offset(owner, 0)
}

pub unconstrained fn balance_of_with_offset<let N: u32>(
self: Self,
owner: AztecAddress,
offset: u32,
) -> u128
where
Note: NoteType + NoteHash + OwnedNote + Packable<N>,
{
) -> u128 {
let mut balance = 0 as u128;
// docs:start:view_notes
let mut options = NoteViewerOptions::new();
Expand Down