Struct PrivateSet
pub struct PrivateSet<Note, Context> {
pub context: Context,
pub storage_slot: Field,
pub owner: AztecAddress,
}
Fields
context: Contextstorage_slot: Fieldowner: AztecAddressImplementations
impl<Note> PrivateSet<Note, &mut PrivateContext>
pub fn insert(self, note: Note) -> NoteMessage<Note>
Inserts a new note into the PrivateSet.
Arguments
note- A newly-created note that you would like to insert into this PrivateSet.
Returns
- NoteMessage
- A type-safe wrapper which makes it clear to the smart contract dev that they now have a choice: they need to decide whether they would like to send the contents of the newly- created note to someone, or not. If they would like to, they have some further choices: - What kind of log to use? (Private log, or offchain log).
- What kind of encryption scheme to use? (Currently only AES128 is supported)
- Whether to constrain delivery of the note, or not.
At the moment, aztec-nr provides limited options.
You can call
.deliver()on the returned type to encrypt and log the note. See NoteMessage for more details.
Note: We're planning a significant refactor of this syntax, to make the syntax of how to encrypt and deliver notes much clearer, and to make the default options much clearer to developers. We will also be enabling easier ways to customize your own note encryption options.
Advanced:
Ultimately, this function inserts the note into the protocol's Note Hash
Tree.
Behind the scenes, we do the following:
- Augment the note with the
storage_slotof this PrivateSet, to convey which set it belongs to. - Augment the note with a
note_type_id, so that it can be correctly filed- away when it is eventually discovered, decrypted, and processed by its intended recipient. (The note_type_id is usually allocated by the #[note] macro). - Provide the contents of the (augmented) note to the PXE, so that it can
store all notes created by the user executing this function.
- The note is also kept in the PXE's memory during execution, in case this newly-created note gets read in some later execution frame of this transaction. In such a case, we feed hints to the kernel to squash: the so-called "transient note", its note log (if applicable), and the nullifier that gets created by the reading function.
- Hash the (augmented) note into a single Field, via the note's own
compute_note_hashmethod. - Push the
note_hashto the PrivateContext. From here, the protocol's kernel circuits will take over and insert the note_hash into the protocol's "note hash tree".- Before insertion, the protocol will:
- "Silo" the
note_hashwith thecontract_addressof the calling function, to yield asiloed_note_hash. This prevents state collisions between different smart contracts. - Ensure uniqueness of the
siloed_note_hash, to prevent Faerie-Gold attacks, by hashing thesiloed_note_hashwith a unique value, to yield aunique_siloed_note_hash(see the protocol spec for more).
- "Silo" the
- Before insertion, the protocol will:
pub fn pop_notes<PreprocessorArgs, FilterArgs, let M: u32>(
self,
options: NoteGetterOptions<Note, M, PreprocessorArgs, FilterArgs>,
) -> BoundedVec<Note, 16>
Pops a collection of "current" notes (i.e. not-yet-nullified notes) which belong to this PrivateSet.
"Pop" indicates that, conceptually, the returned notes will get permanently removed (nullified) from the PrivateSet by this method.
The act of nullifying convinces us that the returned notes are indeed "current" (because if they can be nullified, it means they haven't been nullified already, because a note can only be nullified once).
This means that -- whilst the returned notes should be considered "current" within the currently-executing execution frame of the tx -- they will be not be considered "current" by any later execution frame of this tx (or any future tx).
Notes will be selected from the PXE's database, via an oracle call, according
to the filtering options provided.
Arguments
options- See NoteGetterOptions. Enables the caller to specify the properties of the notes that must be returned by the oracle call to the PXE. The NoteGetterOptions are designed to contain functions which constrain that the returned notes do indeed adhere to the specified options. Those functions are executed within thispop_notescall.
Returns
- BoundedVec<Note, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL>
- A vector of "current" notes, that have been constrained to satisfy the
retrieval criteria specified by the given
options.
- A vector of "current" notes, that have been constrained to satisfy the
retrieval criteria specified by the given
Generic Parameters
PreprocessorArgs- SeeNoteGetterOptions.FilterArgs- SeeNoteGetterOptions.M- The length of the note (in Fields), when packed by the Packable trait.
Advanced:
Reads the notes:
- Gets notes from the PXE, via an oracle call, according to the filtering
optionsprovided. - Constrains that the returned notes do indeed adhere to the
options. (Note: theoptionscontain constrained functions that get invoked within this function). - Asserts that the notes do indeed belong to this calling function's
contract_address, and to this PrivateSet'sstorage_slot. - Computes the note_hash for each note, using the
storage_slotandcontract_addressof this PrivateSet instance. - Asserts that the note_hash does indeed exist:
- For settled notes: makes a request to the kernel to perform a merkle membership check against the historical Note Hashes Tree that this tx is referencing.
- For transient notes: makes a request to the kernel to ensure that the note was indeed emitted by some earlier execution frame of this tx.
Nullifies the notes:
- Computes the nullifier for each note.
- (The nullifier computation differs depending on whether the note is settled or transient).
- Pushes the nullifiers to the PrivateContext. From here, the protocol's
kernel circuits will take over and insert the nullifiers into the
protocol's "nullifier tree".
- Before insertion, the protocol will:
- "Silo" each
nullifierwith thecontract_addressof the calling function, to yield asiloed_nullifier. This prevents nullifier collisions between different smart contracts. - Ensure that each
siloed_nullifierdoes not already exist in the nullifier tree. The nullifier tree is an indexed merkle tree, which supports efficient non-membership proofs.
- "Silo" each
- Before insertion, the protocol will:
pub fn remove(self, retrieved_note: RetrievedNote<Note>)
Permanently removes (conceptually) the given note from this PrivateSet, by nullifying it.
Note that if you obtained the note via get_notes it's much better to use
pop_notes, as pop_notes results in significantly fewer constraints,
due to avoiding an extra hash and read request check.
Arguments
retrieved_note- A note which -- earlier in the calling function's execution -- has been retrieved from the PXE. Theretrieved_noteis constrained to have been read from the i
Returns
- NoteMessage
- A type-safe wrapper which makes it clear to the smart contract dev that they now have a choice: they need to decide whether they would like to send the contents of the newly- created note to someone, or not. If they would like to, they have some further choices: - What kind of log to use? (Private log, or offchain log).
- What kind of encryption scheme to use? (Currently only AES128 is supported)
- Whether to constrain delivery of the note, or not. At the moment, aztec-nr provides limited options. See NoteMessage for further details.
Note: We're planning a significant refactor of this syntax, to make the syntax of how to encrypt and deliver notes much clearer, and to make the default options much clearer to developers. We will also be enabling easier ways to customize your own note encryption options.
pub fn get_notes<PreprocessorArgs, FilterArgs, let M: u32>(
self,
options: NoteGetterOptions<Note, M, PreprocessorArgs, FilterArgs>,
) -> BoundedVec<RetrievedNote<Note>, 16>
Returns a filtered collection of notes from the set.
DANGER: the returned notes do not get nullified within this get_notes
function, and so they cannot necessarily be considered "current" notes.
I.e. you might be reading notes that have already been nullified. It is
this which distinguishes get_notes from pop_notes.
Note that if you later on remove the note it's much better to use
pop_notes as pop_notes results in significantly fewer constrains
due to avoiding 1 read request check.
If you need for your app to see the notes before it can decide which to
nullify (which ideally would not be the case, and you'd be able to rely
on the filter and preprocessor to do this), then you have no resort but
to call get_notes and then remove.
Notes will be selected from the PXE's database, via an oracle call, according
to the filtering options provided.
Arguments
options- See NoteGetterOptions. Enables the caller to specify the properties of the notes that must be returned by the oracle call to the PXE. The NoteGetterOptions are designed to contain functions which constrain that the returned notes do indeed adhere to the specified options. Those functions are executed within thispop_notescall.
Returns
- BoundedVec<Note, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL>
- A vector of "current" notes, that have been constrained to satisfy the
retrieval criteria specified by the given
options.
- A vector of "current" notes, that have been constrained to satisfy the
retrieval criteria specified by the given
Generic Parameters
PreprocessorArgs- SeeNoteGetterOptions.FilterArgs- SeeNoteGetterOptions.M- The length of the note (in Fields), when packed by the Packable trait.
Advanced:
Reads the notes:
- Gets notes from the PXE, via an oracle call, according to the filtering
optionsprovided. - Constrains that the returned notes do indeed adhere to the
options. (Note: theoptionscontain constrained functions that get invoked within this function). - Asserts that the notes do indeed belong to this calling function's
contract_address, and to this PrivateSet'sstorage_slot. - Computes the note_hash for each note, using the
storage_slotandcontract_addressof this PrivateSet instance. - Asserts that the note_hash does indeed exist:
- For settled notes: makes a request to the kernel to perform a merkle membership check against the historical Note Hashes Tree that this tx is referencing.
- For transient notes: makes a request to the kernel to ensure that the note was indeed emitted by some earlier execution frame of this tx.
impl<Note> PrivateSet<Note, UtilityContext>
pub unconstrained fn view_notes(
self,
options: NoteViewerOptions<Note, <Note as Packable>::N>,
) -> BoundedVec<Note, 10>
Returns a collection of notes which belong to this PrivateSet, according
to the given selection options.
Notice that this function is executable only within a UtilityContext, which is an unconstrained environment on the user's local device.
Arguments
options- See NoteGetterOptions. Enables the caller to specify the properties of the notes that must be returned by the oracle call to the PXE.
Trait implementations
impl<Context, Note> OwnedStateVariable<Context> for PrivateSet<Note, Context>
pub fn new(context: Context, storage_slot: Field, owner: AztecAddress) -> Self
PrivateSet is an owned state variable type, which enables you to read, mutate, and write private state. Because it is "owned," you must wrap a PrivateSet inside an Owned state variable when storing it:
E.g.: