Skip to content
Open
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
34 changes: 34 additions & 0 deletions docs/docs-developers/docs/resources/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@ Aztec is in active development. Each version may introduce breaking changes that

## TBD

### [Aztec.nr] Defining a custom `sync_state` function now requires `AztecConfig`

Contracts that previously overrode the default `sync_state` by defining their own function with that name will now get a compile error. Use `AztecConfig::custom_sync_state()` instead.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure if we should call this custom_sync_state() or custom_sync_handler(). What do you think?


The custom hook receives the same parameters as `do_sync_state` and is responsible for calling it if default behavior is also desired. You can perform work before and/or after the default `do_sync_state` call, or skip it entirely.

```diff
+ unconstrained fn my_custom_sync(
+ contract_address: AztecAddress,
+ compute_note_hash: ComputeNoteHash,
+ compute_note_nullifier: ComputeNoteNullifier,
+ process_custom_message: Option<CustomMessageHandler<()>>,
+ offchain_inbox_sync: Option<OffchainInboxSync<()>>,
+ scope: AztecAddress,
+ ) {
+ // optional: work before default sync
+ do_sync_state(contract_address, compute_note_hash, compute_note_nullifier, process_custom_message, offchain_inbox_sync, scope);
+ // optional: work after default sync
+ }

- #[aztec]
+ #[aztec(::aztec::macros::AztecConfig::new().custom_sync_state(crate::my_custom_sync))]
contract MyContract {
- use aztec::macros::functions::external;
-
- #[external("utility")]
- unconstrained fn sync_state(scope: AztecAddress) {
- // custom sync logic
- }
}
```

**Impact**: Only contracts that manually defined a `sync_state` function are affected. Contracts using the default macro-generated `sync_state` require no changes.

### [bb.js / accounts / aztec.nr] Schnorr signatures switched to Poseidon2

The Schnorr challenge hash function changed from `blake2s(pedersen(R.x, pubkey.x, pubkey.y) ‖ message)` to `Poseidon2(DST, R.x, pubkey.x, pubkey.y, message)`, where `DST = poseidon2_hash_bytes("schnorr_grumpkin_poseidon2")` is a domain separation tag binding signatures to this scheme. The change applies end-to-end across the native signer (`bb`), `@aztec/bb.js`, the noir verifier library (`noir-lang/schnorr` v0.2.0 → v0.4.0), and both standard Schnorr account contracts. The auth witness on-wire shape also changes from `[u8; 64]` (the serialized `(s, e)` bytes) to `[Field; 4]` (`[s.lo, s.hi, e.lo, e.hi]`, each scalar split into two 128-bit limbs).
Expand Down
84 changes: 65 additions & 19 deletions noir-projects/aztec-nr/aztec/src/macros/aztec.nr
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ use crate::{
storage::STORAGE_LAYOUT_NAME,
utils::{is_fn_contract_library_method, is_fn_external, is_fn_internal, is_fn_test, module_has_storage},
},
messages::discovery::CustomMessageHandler,
messages::discovery::{CustomMessageHandler, CustomSyncHandler},
};

use compute_note_hash_and_nullifier::generate_contract_library_methods_compute_note_hash_and_nullifier;

/// Configuration for the [`aztec`] macro.
///
/// This type lets users override different parts of the default aztec-nr contract behavior, such
/// as message handling. These are advanced features that require careful understanding of
/// the behavior of these systems.
/// as message handling and state synchronization. These are advanced features that require careful
/// understanding of the behavior of these systems.
///
/// ## Examples
///
Expand All @@ -35,6 +35,7 @@ use compute_note_hash_and_nullifier::generate_contract_library_methods_compute_n
/// ```
pub struct AztecConfig {
custom_message_handler: Option<CustomMessageHandler<()>>,
custom_sync_state: Option<CustomSyncHandler<()>>,
}

impl AztecConfig {
Expand All @@ -43,7 +44,7 @@ impl AztecConfig {
/// Calling `new` is equivalent to invoking the [`aztec`] macro with no parameters. The different methods
/// (e.g. [`AztecConfig::custom_message_handler`]) can then be used to change the default behavior.
pub comptime fn new() -> Self {
Self { custom_message_handler: Option::none() }
Self { custom_message_handler: Option::none(), custom_sync_state: Option::none() }
}

/// Sets a handler for custom messages.
Expand All @@ -53,8 +54,21 @@ impl AztecConfig {
///
/// `handler` must be a function that conforms to the
/// [`crate::messages::discovery::CustomMessageHandler`] type signature.
pub comptime fn custom_message_handler(_self: Self, handler: CustomMessageHandler<()>) -> Self {
Self { custom_message_handler: Option::some(handler) }
pub comptime fn custom_message_handler(self, handler: CustomMessageHandler<()>) -> Self {
Self { custom_message_handler: Option::some(handler), custom_sync_state: self.custom_sync_state }
}

/// Overrides the default state synchronization logic.
///
/// The generated `sync_state` function will call `handler` instead of
/// [`crate::messages::discovery::do_sync_state`]. The handler receives all of the same parameters, so it can
/// run custom logic (e.g. fetching and decrypting custom logs) before, after, or instead of calling
/// `do_sync_state`.
///
/// `handler` must be a function that conforms to the
/// [`crate::messages::discovery::CustomSyncHandler`] type signature.
pub comptime fn custom_sync_state(self, handler: CustomSyncHandler<()>) -> Self {
Self { custom_message_handler: self.custom_message_handler, custom_sync_state: Option::some(handler) }
}
}

Expand Down Expand Up @@ -105,7 +119,7 @@ pub comptime fn aztec(m: Module, args: [AztecConfig]) -> Quoted {
let fn_abi_exports = create_fn_abi_exports(m);

// We generate `_compute_note_hash`, `_compute_note_nullifier` (and the deprecated
// `_compute_note_hash_and_nullifier` wrapper) and `sync_state` functions only if they are not already implemented.
// `_compute_note_hash_and_nullifier` wrapper) only if they are not already implemented.
// If they are implemented we just insert empty quotes.
let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {
// Note that we don't test for `_compute_note_hash` or `_compute_note_nullifier` in order to make this simpler
Expand All @@ -128,12 +142,22 @@ pub comptime fn aztec(m: Module, args: [AztecConfig]) -> Quoted {
Option::some(aztec::messages::processing::offchain::sync_inbox)
};

let sync_state_fn_and_abi_export = if !m.functions().any(|f| f.name() == quote { sync_state }) {
generate_sync_state(process_custom_message_option, offchain_inbox_sync_option)
if m.functions().any(|f| f.name() == quote { sync_state }) {
panic(
"User-defined 'sync_state' is not allowed. Use AztecConfig::custom_sync_state() to customize sync behavior.",
);
}

let custom_sync_handler = if config.custom_sync_state.is_some() {
let handler = config.custom_sync_state.unwrap();
Option::some(quote { $handler })
} else {
quote {}
Option::none()
};

let sync_state_fn_and_abi_export =
generate_sync_state(process_custom_message_option, offchain_inbox_sync_option, custom_sync_handler);

if m.functions().any(|f| f.name() == quote { offchain_receive }) {
panic(
"User-defined 'offchain_receive' is not allowed. The function is auto-injected by the #[aztec] macro. See https://docs.aztec.network/errors/7",
Expand Down Expand Up @@ -223,7 +247,36 @@ comptime fn generate_contract_interface(m: Module) -> Quoted {
}

/// Generates the `sync_state` utility function that performs message discovery.
comptime fn generate_sync_state(process_custom_message_option: Quoted, offchain_inbox_sync_option: Quoted) -> Quoted {
comptime fn generate_sync_state(
process_custom_message_option: Quoted,
offchain_inbox_sync_option: Quoted,
custom_sync_handler: Option<Quoted>,
) -> Quoted {
let body = if custom_sync_handler.is_some() {
let handler = custom_sync_handler.unwrap();
quote {
$handler(
address,
_compute_note_hash,
_compute_note_nullifier,
$process_custom_message_option,
$offchain_inbox_sync_option,
scope,
);
}
} else {
quote {
aztec::messages::discovery::do_sync_state(
address,
_compute_note_hash,
_compute_note_nullifier,
$process_custom_message_option,
$offchain_inbox_sync_option,
scope,
);
}
};

quote {
pub struct sync_state_parameters {
pub scope: aztec::protocol::address::AztecAddress,
Expand All @@ -237,14 +290,7 @@ comptime fn generate_sync_state(process_custom_message_option: Quoted, offchain_
#[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]
unconstrained fn sync_state(scope: aztec::protocol::address::AztecAddress) {
let address = aztec::context::UtilityContext::new().this_address();
aztec::messages::discovery::do_sync_state(
address,
_compute_note_hash,
_compute_note_nullifier,
$process_custom_message_option,
$offchain_inbox_sync_option,
scope,
);
$body
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ pub type CustomMessageHandler<Env> = unconstrained fn[Env](
/* message_context */ MessageContext,
/* scope */ AztecAddress);

/// Custom state synchronization handler.
///
/// When set via [`crate::macros::AztecConfig::custom_sync_state`], the generated `sync_state` function will call
/// this handler instead of [`do_sync_state`]. It receives all of the same parameters, so it can run custom logic
/// (e.g. fetching and decrypting custom logs) before, after, or instead of calling [`do_sync_state`].
pub type CustomSyncHandler<Env> = unconstrained fn[Env](
/* contract_address */ AztecAddress,
/* compute_note_hash */ ComputeNoteHash,
/* compute_note_nullifier */ ComputeNoteNullifier,
/* process_custom_message */ Option<CustomMessageHandler<()>>,
/* offchain_inbox_sync */ Option<OffchainInboxSync<()>>,
/* scope */ AztecAddress,
);

/// Synchronizes the contract's private state with the network.
///
/// As blocks are mined, it is possible for a contract's private state to change (e.g. with new notes being created),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ global MAX_MSG_TTL: u64 = MAX_TX_LIFETIME + TX_EXPIRATION_TOLERANCE;
///
/// The only current implementation of an `OffchainInboxSync` is [`sync_inbox`], which manages an inbox with expiration
/// based eviction and automatic transaction context resolution.
pub(crate) type OffchainInboxSync<Env> = unconstrained fn[Env](
pub type OffchainInboxSync<Env> = unconstrained fn[Env](
/* contract_address */AztecAddress, /* scope */ AztecAddress) -> EphemeralArray<OffchainMessageWithContext>;

/// A message delivered via the `offchain_receive` utility function.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "user_defined_sync_state"
type = "contract"
authors = [""]

[dependencies]
aztec = { path = "../../../../aztec-nr/aztec" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// The name `sync_state` is reserved for the function auto-injected by the #[aztec] macro.
/// Use AztecConfig::custom_sync_state() to customize sync behavior.
use aztec::macros::aztec;

#[aztec]
contract UserDefinedSyncState {
use aztec::macros::functions::external;
use aztec::protocol::address::AztecAddress;

#[external("private")]
fn sync_state(_scope: AztecAddress) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ error: Argument from in function foo must be of type AztecAddress, but is of typ
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:97:21
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:111:21
3: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:9
4: [T]::map
at std/vector.nr:67:33
5: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:41
6: generate_public_external
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:134:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:131:9
7: create_authorize_once_check
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/helpers.nr:72:9

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ error: Function foo does not have a from parameter. Please specify which one to
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:97:21
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:111:21
3: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:9
4: [T]::map
at std/vector.nr:67:33
5: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:41
6: generate_public_external
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:134:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:131:9
7: create_authorize_once_check
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/helpers.nr:67:9

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ error: Function foo does not have a authwit_nonce. Please specify which one to u
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:97:21
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:111:21
3: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:9
4: [T]::map
at std/vector.nr:67:33
5: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:41
6: generate_public_external
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:134:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:131:9
7: create_authorize_once_check
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/helpers.nr:81:9

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ error: Argument authwit_nonce in function foo must be of type Field, but is of t
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:97:21
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:111:21
3: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:9
4: [T]::map
at std/vector.nr:67:33
5: process_functions
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/mod.nr:48:41
6: generate_public_external
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:134:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr:131:9
7: create_authorize_once_check
at <repo>/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/helpers.nr:86:9

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ error: #[aztec] expects 0 or 1 arguments, got 2
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:89:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:103:9

Aborting due to 1 previous error
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ error: Function _assert_is_owner must be marked as either #[external(...)], #[in
1: #[aztec]
at src/main.nr:18:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:93:5
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:107:5
3: check_each_fn_macroified
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:295:13
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:341:13

error: cannot find `self` in this scope
┌─ src/main.nr:41:9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ error: InvalidNote has a packed length of 9 fields, which exceeds the maximum al
= Call stack:
1: generate_sync_state
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:240:13
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:269:13
2: do_sync_state
at <repo>/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr:130:5
at <repo>/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr:144:5
3: EphemeralArray<T>::for_each
at <repo>/noir-projects/aztec-nr/aztec/src/ephemeral/mod.nr:99:13
4: do_sync_state
at <repo>/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr:139:13
at <repo>/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr:153:13
5: process_message_ciphertext
at <repo>/noir-projects/aztec-nr/aztec/src/messages/discovery/process_message.nr:41:9
6: process_message_plaintext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ error: Public function selector collision detected between functions 'fn_selecto
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:145:27
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:169:27
3: generate_public_dispatch
at <repo>/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr:20:19
4: [T]::map
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ error: Function foo must be marked as either #[external(...)], #[internal(...)],
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:93:5
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:107:5
3: check_each_fn_macroified
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:295:13
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:341:13

Aborting due to 1 previous error
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ error: User-defined 'offchain_receive' is not allowed. The function is auto-inje
1: #[aztec]
at src/main.nr:4:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:138:9
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:162:9

Aborting due to 1 previous error
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: tests/snapshots.rs
expression: stderr
---
error: User-defined 'sync_state' is not allowed. Use AztecConfig::custom_sync_state() to customize sync behavior.
┌─ std/panic.nr:8:12
8 │ assert(false, message);
│ ----- Assertion failed
= Call stack:
1: #[aztec]
at src/main.nr:5:1
2: aztec
at <repo>/noir-projects/aztec-nr/aztec/src/macros/aztec.nr:146:9

Aborting due to 1 previous error
Loading
Loading