Skip to content

Commit

Permalink
feat!: aztec_macros are dead, long live aztec::macros (#8438)
Browse files Browse the repository at this point in the history
Requires noir sync and noir-lang/noir#6078 to
be merged so `compute_note_hash_and_optionally_a_nullifier` can be
autogenerated.

Also, fixed a lot of explicit numeric generics, used arithmetics on them
(yay!!) and introduced a macro for partial notes

---------

Co-authored-by: TomAFrench <tom@tomfren.ch>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: benesjan <janbenes1234@gmail.com>
Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
Co-authored-by: Ary Borenszweig <asterite@gmail.com>
  • Loading branch information
6 people authored Sep 24, 2024
1 parent 4641004 commit 7cbabd6
Show file tree
Hide file tree
Showing 147 changed files with 3,648 additions and 2,026 deletions.
2 changes: 1 addition & 1 deletion avm-transpiler/src/transpile_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl From<CompiledAcirContractArtifact> for TranspiledContractArtifact {

for function in contract.functions {
// TODO(4269): once functions are tagged for transpilation to AVM, check tag
if function.custom_attributes.contains(&"aztec(public)".to_string()) {
if function.custom_attributes.contains(&"public".to_string()) {
info!("Transpiling AVM function {} on contract {}", function.name, contract.name);
// Extract Brillig Opcodes from acir
let acir_program = function.bytecode;
Expand Down
20 changes: 12 additions & 8 deletions boxes/boxes/react/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use dep::aztec::macros::aztec;

#[aztec]
contract BoxReact {
use dep::aztec::{
keys::public_keys::{IvpkM, OvpkM},
prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader, Point},
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys,
macros::{storage::storage, functions::{private, public, initializer}}
};
use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};
use dep::value_note::value_note::ValueNote;

#[aztec(storage)]
struct Storage {
numbers: Map<AztecAddress, PrivateMutable<ValueNote>>,
#[storage]
struct Storage<Context> {
numbers: Map<AztecAddress, PrivateMutable<ValueNote, Context>, Context>,
}

#[aztec(private)]
#[aztec(initializer)]
#[private]
#[initializer]
fn constructor(
number: Field,
owner: AztecAddress,
Expand All @@ -25,7 +29,7 @@ contract BoxReact {
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m, owner));
}

#[aztec(private)]
#[private]
fn setNumber(
number: Field,
owner: AztecAddress,
Expand Down
18 changes: 11 additions & 7 deletions boxes/boxes/vanilla/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use dep::aztec::macros::aztec;

#[aztec]
contract Vanilla {
use dep::aztec::{
keys::public_keys::{IvpkM, OvpkM},
prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader, Point},
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys,
macros::{storage::storage, functions::{private, public, initializer}}
};
use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};

#[aztec(storage)]
struct Storage {
numbers: Map<AztecAddress, PrivateMutable<ValueNote>>,
#[storage]
struct Storage<Context> {
numbers: Map<AztecAddress, PrivateMutable<ValueNote, Context>, Context>,
}

#[aztec(private)]
#[aztec(initializer)]
#[private]
#[initializer]
fn constructor(
number: Field,
owner: AztecAddress,
Expand All @@ -25,7 +29,7 @@ contract Vanilla {
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m, owner));
}

#[aztec(private)]
#[private]
fn setNumber(
number: Field,
owner: AztecAddress,
Expand Down
7 changes: 5 additions & 2 deletions boxes/init/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

use dep::aztec::macros::aztec;

#[aztec]
contract Main {
#[aztec(private)]
#[aztec(initializer)]
#[private]
#[initializer]
fn constructor() { }
}
4 changes: 2 additions & 2 deletions docs/docs/aztec/concepts/storage/partial_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ Then we just emit `P_a.x` and `P_b.x` as a note hashes, and we're done!

[`NoteInterface.nr`](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/note/note_interface.nr) implements `compute_note_hiding_point`, which takes a note and computes the point "hides" it.

This is implemented in the example token contract:
This is implemented by applying the `partial_note` attribute:

#include_code compute_note_hiding_point noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr rust
#include_code TokenNote noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr rust

Those `G_x` are generators that generated [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-projects/aztec-nr/aztec/src/generators.nr). Anyone can use them for separating different fields in a "partial note".

Expand Down
81 changes: 81 additions & 0 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,87 @@ The `select` function in both `NoteGetterOptions` and `NoteViewerOptions` no lon
+ options.select(ValueNote::properties().value, Comparator.EQ, amount)
```

### [Aztec.nr] Changes to contract definition

We've migrated the Aztec macros to use the newly introduce meta programming Noir feature. Due to being Noir-based, the new macros are less obscure and can be more easily modified.

As part of this transition, some changes need to be applied to Aztec contracts:

- The top level `contract` block needs to have the `#[aztec]` macro applied to it.
- All `#[aztec(name)]` macros are renamed to `#[name]`.
- The storage struct (the one that gets the `#[storage]` macro applied) but be generic over a `Context` type, and all state variables receive this type as their last generic type parameter.

```diff
+ use dep::aztec::macros::aztec;

#[aztec]
contract Token {
+ use dep::aztec::macros::{storage::storage, events::event, functions::{initializer, private, view, public}};

- #[aztec(storage)]
- struct Storage {
+ #[storage]
+ struct Storage<Context> {
- admin: PublicMutable<AztecAddress>,
+ admin: PublicMutable<AztecAddress, Context>,
- minters: Map<AztecAddress, PublicMutable<bool>>,
+ minters: Map<AztecAddress, PublicMutable<bool, Context>, Context>,
}

- #[aztec(public)]
- #[aztec(initializer)]
+ #[public]
+ #[initializer]
fn constructor(admin: AztecAddress, name: str<31>, symbol: str<31>, decimals: u8) {
...
}

- #[aztec(public)]
- #[aztec(view)]
- fn public_get_name() -> FieldCompressedString {
+ #[public]
+ #[view]
fn public_get_name() -> FieldCompressedString {
...
}
```

### [Aztec.nr] Changes to `NoteInterface`

The new macro model prevents partial trait auto-implementation: they either implement the entire trait or none of it. This means users can no longer implement part of `NoteInterface` and have the rest be auto-implemented.

For this reason we've separated the methods which are auto-implemented and those which needs to be implemented manually into two separate traits: the auto-implemented ones stay in the `NoteInterface` trace and the manually implemented ones were moved to `NullifiableNote` (name likely to change):

```diff
-#[aztec(note)]
+#[note]
struct AddressNote {
...
}

-impl NoteInterface<ADDRESS_NOTE_LEN, ADDRESS_NOTE_BYTES_LEN> for AddressNote {
+impl NullifiableNote for AddressNote {
fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field {
...
}

fn compute_nullifier_without_context(self) -> Field {
...
}
}
```

### [Aztec.nr] Changes to contract interface

The `Contract::storage()` static method has been renamed to `Contract::storage_layout()`.

```diff
- let fee_payer_balances_slot = derive_storage_slot_in_map(Token::storage().balances.slot, fee_payer);
- let user_balances_slot = derive_storage_slot_in_map(Token::storage().balances.slot, user);
+ let fee_payer_balances_slot = derive_storage_slot_in_map(Token::storage_layout().balances.slot, fee_payer);
+ let user_balances_slot = derive_storage_slot_in_map(Token::storage_layout().balances.slot, user);
```

## 0.53.0

### [Aztec.nr] Remove `OwnedNote` and create `UintNote`
Expand Down
18 changes: 6 additions & 12 deletions noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
use dep::aztec::{
protocol_types::{
address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator
},
note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_nullify},
oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext
protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator},
note::{note_header::NoteHeader, note_interface::NullifiableNote, utils::compute_note_hash_for_nullify},
oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext,
macros::notes::note
};

global ADDRESS_NOTE_LEN: u32 = 3;
// ADDRESS_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)
global ADDRESS_NOTE_BYTES_LEN: u32 = 3 * 32 + 64;

// docs:start:address_note_def
// docs:start:address_note_struct
// Stores an address
#[aztec(note)]
#[note]
struct AddressNote {
address: AztecAddress,
// The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent.
Expand All @@ -23,7 +17,7 @@ struct AddressNote {
}
// docs:end:address_note_struct

impl NoteInterface<ADDRESS_NOTE_LEN, ADDRESS_NOTE_BYTES_LEN> for AddressNote {
impl NullifiableNote for AddressNote {

fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field {
let secret = context.request_nsk_app(self.npk_m_hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use dep::protocol_types::{
};

// When finished, one can call .finish() to convert back to the abi
struct PrivateContext {
pub struct PrivateContext {
// docs:start:private-context
inputs: PrivateContextInputs,
side_effect_counter: u32,
Expand Down
Loading

0 comments on commit 7cbabd6

Please sign in to comment.