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
8 changes: 6 additions & 2 deletions noir-projects/aztec-nr/aztec/src/capsules/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ impl<T> CapsuleArray<T> {
capsules::store(self.contract_address, self.base_slot, current_length - 1);
}

/// Iterates over the entire array, calling the callback with all values and their array index. The order in which
/// values are processed is arbitrary.
/// Calls a function on each element of the array.
///
/// The function `f` is called once with each array value and its corresponding index. The order in which values
/// are processed is arbitrary.
///
/// ## Array Mutation
///
/// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:
/// ```noir
Expand Down
60 changes: 40 additions & 20 deletions noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::protocol::{address::AztecAddress, logging::{debug_log, debug_log_format}};

pub mod nonce_discovery;
pub mod partial_notes;
pub mod private_events;
pub(crate) mod nonce_discovery;
pub(crate) mod partial_notes;
pub(crate) mod private_events;
pub mod private_notes;
pub mod process_message;

Expand All @@ -20,22 +20,38 @@ use crate::{
};

pub struct NoteHashAndNullifier {
/// The result of NoteHash::compute_note_hash
/// The result of [`crate::note::note_interface::NoteHash::compute_note_hash`].
pub note_hash: Field,
/// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained).
/// This is `None` if the nullifier cannot be computed (e.g., because the nullifier hiding key is not available).
/// The result of [`crate::note::note_interface::NoteHash::compute_nullifier_unconstrained`].
///
/// This value is unconstrained, as all of message discovery is unconstrained. It is `None` if the nullifier
/// cannot be computed (e.g. because the nullifier hiding key is not available).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it slightly confusing here that we mention that only this value is unconstrained even though whenever we use the NoteHashAndNullifier type even the note_hash is unconstrained.

I get what you mean though

pub inner_nullifier: Option<Field>,
}

/// A function which takes a note's packed content, address of the emitting contract, note nonce, storage slot and note
/// type ID and attempts to compute its note hash (not hashed by note nonce nor siloed by address) and inner nullifier
/// (not siloed by address).
/// A contract's way of computing note hashes and nullifiers.
///
/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in
/// a contract. The `#[aztec]` macro automatically creates such a contract library method called
/// `_compute_note_hash_and_nullifier`, which looks something like this:
/// Each contract in the network is free to compute their note's hash and nullifiers as they see fit - the hash
/// function itself and the nullifier derivation are not enshrined or standardized. Some aztec-nr functions however do
/// need to know the details of this computation (e.g. when finding new notes), which is what this type represents.
///
/// ```
/// This function takes a note's packed content, storage slot, note type ID, address of the emitting contract,
/// randomness and note nonce, and attempts to compute its inner note hash (not siloed by address nor uniqued by nonce)
/// and inner nullifier (not siloed by address).
///
/// ## Transient Notes
///
/// This function is meant to always be used on **settled** notes, i.e. those that have been inserted into the trees
/// and for which the nonce is known. It is never invoked in the context of a transient note, as those are not involved
/// in message processing.
///
/// ## Automatic Implementation
///
/// The [`[#aztec]`](crate::macros::aztec::aztec) macro automatically creates a correct implementation of this function
/// for each contract by inspecting all note types in use and the storage layout. This injected function is a
/// `#[contract_library_function]` called `_compute_note_hash_and_nullifier`, and it looks something like this:
///
/// ```noir
/// |packed_note, owner, storage_slot, note_type_id, contract_address, randomness, note_nonce| {
/// if note_type_id == MyNoteType::get_id() {
/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);
Expand Down Expand Up @@ -78,15 +94,14 @@ pub type CustomMessageHandler<Env> = unconstrained fn[Env](
/* msg_content */ BoundedVec<Field, MAX_MESSAGE_CONTENT_LEN>,
/* message_context */ MessageContext);

/// Performs the state synchronization process, in which private logs are downloaded and inspected to find new private
/// notes, partial notes and events, etc., and pending partial notes are processed to search for their completion logs.
/// This is the mechanism via which a contract updates its knowledge of its private state.
/// Synchronizes the contract's private state with the network.
///
/// Note that the state is synchronized up to the latest block synchronized by PXE (referred to as "anchor block").
/// That should be close to the chain tip as block synchronization is performed before contract function simulation is
/// done.
/// As blocks are mined, it is possible for a contract's private state to change (e.g. with new notes being created),
/// but because these changes are private they will be invisible to most actors. This is the function that processes
/// new transactions in order to discover new notes, events, and other kinds of private state changes.
///
/// Receives the address of the contract on which discovery is performed along with the contract's configuration.
/// The private state will be synchronized up to the block that will be used for private transactions (i.e. the anchor
/// block. This will typically be close to the tip of the chain.
pub unconstrained fn do_sync_state<ComputeNoteHashAndNullifierEnv, CustomMessageHandlerEnv>(
contract_address: AztecAddress,
compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier<ComputeNoteHashAndNullifierEnv>,
Expand All @@ -113,6 +128,11 @@ pub unconstrained fn do_sync_state<ComputeNoteHashAndNullifierEnv, CustomMessage
message_ciphertext,
pending_tagged_log.context,
);

// We need to delete each log from the array so that we won't process them again. `CapsuleArray::for_each`
// allows deletion of the current element during iteration, so this is safe.
// Note that this (and all other database changes) will only be committed if contract execution succeeds,
// including any enqueued validation requests.
logs.remove(i);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ use crate::protocol::{

/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*
/// the complete note information, since it does not include content, storage slot, etc.
pub struct DiscoveredNoteInfo {
pub note_nonce: Field,
pub note_hash: Field,
pub inner_nullifier: Field,
pub(crate) struct DiscoveredNoteInfo {
pub(crate) note_nonce: Field,
pub(crate) note_hash: Field,
pub(crate) inner_nullifier: Field,
}

/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible
Expand All @@ -23,7 +23,7 @@ pub struct DiscoveredNoteInfo {
///
/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,
/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.
pub unconstrained fn attempt_note_nonce_discovery<Env>(
pub(crate) unconstrained fn attempt_note_nonce_discovery<Env>(
unique_note_hashes_in_tx: BoundedVec<Field, MAX_NOTE_HASHES_PER_TX>,
first_nullifier_in_tx: Field,
compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier<Env>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::protocol::{
};

/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.
pub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(
pub(crate) global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(
"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT".as_bytes(),
);

Expand All @@ -37,7 +37,7 @@ pub(crate) struct DeliveredPendingPartialNote {
pub(crate) recipient: AztecAddress,
}

pub unconstrained fn process_partial_note_private_msg(
pub(crate) unconstrained fn process_partial_note_private_msg(
contract_address: AztecAddress,
recipient: AztecAddress,
msg_metadata: u64,
Expand Down Expand Up @@ -67,7 +67,7 @@ pub unconstrained fn process_partial_note_private_msg(

/// Searches for logs that would result in the completion of pending partial notes, ultimately resulting in the notes
/// being delivered to PXE if completed.
pub unconstrained fn fetch_and_process_partial_note_completion_logs<Env>(
pub(crate) unconstrained fn fetch_and_process_partial_note_completion_logs<Env>(
contract_address: AztecAddress,
compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier<Env>,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
};
use crate::protocol::{address::AztecAddress, traits::ToField};

pub unconstrained fn process_private_event_msg(
pub(crate) unconstrained fn process_private_event_msg(
contract_address: AztecAddress,
recipient: AztecAddress,
msg_metadata: u64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::messages::{
};
use crate::protocol::{address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, logging::debug_log_format};

pub unconstrained fn process_private_note_msg<Env>(
pub(crate) unconstrained fn process_private_note_msg<Env>(
contract_address: AztecAddress,
tx_hash: Field,
unique_note_hashes_in_tx: BoundedVec<Field, MAX_NOTE_HASHES_PER_TX>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ pub unconstrained fn process_message_ciphertext<ComputeNoteHashAndNullifierEnv,
);
} else {
debug_log_format(
"Found invalid message from tx {0}, ignoring",
"Could not decrypt message ciphertext from tx {0}, ignoring",
[message_context.tx_hash],
);
}
}

pub unconstrained fn process_message_plaintext<ComputeNoteHashAndNullifierEnv, CustomMessageHandlerEnv>(
pub(crate) unconstrained fn process_message_plaintext<ComputeNoteHashAndNullifierEnv, CustomMessageHandlerEnv>(
contract_address: AztecAddress,
compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier<ComputeNoteHashAndNullifierEnv>,
process_custom_message: Option<CustomMessageHandler<CustomMessageHandlerEnv>>,
Expand Down
Loading