Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): Aztecnr notes docs #7168

Merged
merged 19 commits into from
Aug 6, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Using Address Note in Aztec.nr
---

Address notes hold one main property of the type `AztecAddress`. It also holds `npk_m_hash` and `randomness`, similar to other note types.

## AddressNote

This is the AddressNote struct:

#include_code address_note_struct noir-projects/aztec-nr/address-note/src/address_note.nr rust

## Importing AddressNote

### In Nargo.toml

```toml
address_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/aztec-nr/address-note" }
```

### In your contract

#include_code addressnote_import noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr rust

## Working with AddressNote

### Creating a new note

Creating a new `AddressNote` takes the following args:

- `address` (`AztecAddress`): the address to store in the AddressNote
- `npk_m_hash` (`Field`): the master nullifier public key hash of the user

#include_code addressnote_new noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr rust

In this example, `owner` is the `address` and the `npk_m_hash` of the donor was computed earlier.

## Learn more

- [Keys, including nullifier keys and outgoing viewer](../../../../aztec/concepts/accounts/keys.md)
- [How to write a custom note](./custom_note.md)
- [AddressNote reference](https://docs.aztec.network/reference/smart_contract_reference/aztec-nr/address-note/address_note)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: Using custom note types in Aztec.nr
---

It may be useful to write a custom note type if you want to use a specific type of private data or struct that does not have a default implementation in Aztec.nr. If you create a note that uses a custom note type, you are able to nullify that note with one nullifier. This is more secure and less expensive than using multiple separate notes.

As an example, if you are developing a card game, you may want to store multiple pieces of data in each card. Rather than storing each of these pieces of data in their own note, you can use a custom note to define the card, and then nullify (or exchange ownership of) the card when it has been used.

If you want to work with values or addresses, you can check out [ValueNote](./value_note.md) or [AddressNote](./address_note.md).

## Define a custom note type

You will likely want to define your note in a new file and import it into your contract.

A custom note type can be defined with the macro `#[aztec(note)]` used on a struct:

#include_code state_vars-CardNote noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr rust

In this example, we are implementing a card note that holds a number of points as `u8`.

## Implement NoteInterface

You will need to implement a note interface for your note. Most of this is automatically generated by the `#[aztec(note)]` macro but can be overwritten. For your reference, this is what a note interface looks like:

#include_code note_interface noir-projects/aztec-nr/aztec/src/note/note_interface.nr rust

You will need to implement the functions `compute_note_hash_and_nullifier()` and `compute_note_hash_and_nullifier_without_context()` which tells Aztec how to compute nullifiers for your note.

#include_code note_interface noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr rust

In this example, these functions compute the note hash by using `compute_note_hash_for_consumption` and then generate a nullifier by hashing this note hash together with a secret.

### Methods

You will likely want to implement methods in order to use your note easily within contracts. For example, this may be what a `new` method can look like, for creating a new note:

#include_code cardnote_impl noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr rust

If you are also planning to be able to access the data with a note in public state, you will need to implement a method for serializing the note. This might look something like this:

#include_code serialize noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr rust

## Further reading

- [Macros reference](../../../../reference/smart_contract_reference/macros.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Notes
sidebar_position: 6
---

Notes are the fundamental data structure in Aztec when working with private state. In this section there are guides about how to work with `AddressNote`, `ValueNote`, and custom notes in Aztec.nr. You can learn more about notes in the [concepts section](../../../../aztec/concepts/state_model/index.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: Using Value Notes in Aztec.nr
---

ValueNotes hold one main property - a `value` - and have utils useful for manipulating this value, such as incrementing and decrementing it similarly to an integer.

## ValueNote

This is the ValueNote struct:

#include_code value-note-def noir-projects/aztec-nr/value-note/src/value_note.nr rust

## Importing ValueNote

### In Nargo.toml

```toml
value_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/aztec-nr/value-note" }
```

### In your contract

#include_code import_valuenote noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust

## Working with ValueNote

### Creating a new note

Creating a new `ValueNote` takes the following args:

- `value` (`Field`): the value of the ValueNote
- `npk_m_hash` (`Field`): the master nullifier public key hash of the user

#include_code valuenote_new noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust

In this example, `amount` is the `value` and the `npk_m_hash` of the donor was computed earlier.

### Getting a balance

A user may have multiple notes in a set that all refer to the same content (e.g. a set of notes representing a single token balance). By using the `ValueNote` type to represent token balances, you do not have to manually add each of these notes and can instead use a helper function `get_balance()`.

It takes one argument - the set of notes.

#include_code get_balance noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr rust

This can only be used in an unconstrained function.

### Incrementing and decrementing

Both `increment` and `decrement` functions take the same args:

#include_code increment_args noir-projects/aztec-nr/value-note/src/utils.nr rust

Note that this will create a new note in the set of notes passed as the first argument.
For example:
#include_code increment_valuenote noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr rust

The `decrement` function works similarly except the `amount` is the number that the value will be decremented by, and it will fail if the sum of the selected notes is less than the amount.

## Learn more

- [Keys, including nullifier keys and outgoing viewer](../../../../aztec/concepts/accounts/keys.md)
- [How to write a custom note](./custom_note.md)
- [ValueNote reference](https://docs.aztec.network/reference/smart_contract_reference/aztec-nr/value-note/value_note)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Portals
sidebar_position: 6
sidebar_position: 7
---

A portal is a point of contact between L1 and a contract on Aztec. For applications such as token bridges, this is the point where the tokens are held on L1 while used in L2. Note, that a portal doesn't actually need to be a contract, it could be any address on L1.
2 changes: 2 additions & 0 deletions noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ global ADDRESS_NOTE_LEN: Field = 3;
global ADDRESS_NOTE_BYTES_LEN: Field = 3 * 32 + 64;

// docs:start:address_note_def
// docs:start:address_note_struct
// Stores an address
#[aztec(note)]
struct AddressNote {
Expand All @@ -20,6 +21,7 @@ struct AddressNote {
npk_m_hash: Field,
randomness: Field,
}
// docs:end:address_note_struct

impl NoteInterface<ADDRESS_NOTE_LEN, ADDRESS_NOTE_BYTES_LEN> for AddressNote {

Expand Down
3 changes: 2 additions & 1 deletion noir-projects/aztec-nr/value-note/src/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG
// Creates a new note for the recipient.
// Inserts it to the recipient's set of notes.
pub fn increment(
// docs:start:increment_args
balance: PrivateSet<ValueNote, &mut PrivateContext>,
amount: Field,
recipient: AztecAddress,
outgoing_viewer: AztecAddress
outgoing_viewer: AztecAddress // docs:end:increment_args
) {
let header = balance.context.get_header();
let recipient_npk_m_hash = header.get_npk_m_hash(balance.context, recipient);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ contract Benchmarking {
// Creates a new value note for the target owner. Use this method to seed an initial set of notes.
#[aztec(private)]
fn create_note(owner: AztecAddress, outgoing_viewer: AztecAddress, value: Field) {
// docs:start:increment_valuenote
increment(storage.notes.at(owner), value, owner, outgoing_viewer);
// docs:end:increment_valuenote
}

// Deletes a note at a specific index in the set and creates a new one with the same value.
// We explicitly pass in the note index so we can ensure we consume different notes when sending
// multiple txs that will land on the same block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ contract Crowdfunding {
state_vars::{PrivateSet, PublicImmutable, SharedImmutable}
};
use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event;
// docs:start:import_valuenote
use dep::value_note::value_note::ValueNote;
// docs:end:import_valuenote
use dep::token::Token;
// docs:end:all-deps

Expand Down Expand Up @@ -78,7 +80,9 @@ contract Crowdfunding {
// 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim
// contract by proving that the hash of this note exists in the note hash tree.
let donor_npk_m_hash = header.get_npk_m_hash(&mut context, donor);
// docs:start:valuenote_new
let mut note = ValueNote::new(amount as Field, donor_npk_m_hash);
// docs:end:valuenote_new
storage.donation_receipts.insert(&mut note).emit(encode_and_encrypt_note(&mut context, donor, donor));
}
// docs:end:donate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ struct CardNote {
}
// docs:end:state_vars-CardNote

// docs:start:cardnote_impl
impl CardNote {
pub fn new(points: u8, randomness: Field, npk_m_hash: Field) -> Self {
CardNote { points, randomness, npk_m_hash, header: NoteHeader::empty() }
}
}
// docs:end:cardnote_impl

// docs:start:note_interface
impl NoteInterface<CARD_NOTE_LEN, CARD_NOTE_BYTES_LEN> for CardNote {
fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {
let note_hash_for_nullify = compute_note_hash_for_consumption(self);
Expand All @@ -54,12 +57,15 @@ impl NoteInterface<CARD_NOTE_LEN, CARD_NOTE_BYTES_LEN> for CardNote {
(note_hash_for_nullify, nullifier)
}
}
// docs:end:note_interface

// docs:start:serialize
impl Serialize<3> for CardNote {
fn serialize(self) -> [Field; 3] {
[ self.points.to_field(), self.randomness, self.npk_m_hash.to_field() ]
}
}
// docs:end:serialize

impl Eq for CardNote {
fn eq(self, other: Self) -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ contract Escrow {
use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable};
use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;

// docs:start:addressnote_import
use dep::address_note::address_note::AddressNote;

// docs:end:addressnote_import
use dep::token::Token;

#[aztec(storage)]
Expand All @@ -18,8 +19,9 @@ contract Escrow {
fn constructor(owner: AztecAddress) {
let header = context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner);

// docs:start:addressnote_new
let mut note = AddressNote::new(owner, owner_npk_m_hash);
// docs:end:addressnote_new
storage.owner.initialize(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,14 @@ contract InclusionProofs {
fn test_storage_historical_read_unset_slot(block_number: u32 // The block at which we'll read the public storage value
) {
let header = context.get_header_at(block_number);

// docs:start:public_storage_historical_read
assert_eq(
// docs:start:public_storage_historical_read
header.public_storage_historical_read(
storage.public_unused_value.storage_slot,
context.this_address()
// docs:end:public_storage_historical_read
), 0
);
// docs:end:public_storage_historical_read
}

#[aztec(private)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ contract StatefulTest {
unconstrained fn summed_values(owner: AztecAddress) -> pub Field {
let owner_balance = storage.notes.at(owner);

// docs:start:get_balance
// Return the sum of all notes in the set.
balance_utils::get_balance(owner_balance)
// docs:end:get_balance
}

#[aztec(public)]
Expand Down
Loading