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): Note type IDs and compute_note_hash_and_nullifier page #4636

Merged
merged 22 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bed2bb7
note type IDs
catmcgee Feb 16, 2024
14f4ef5
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 16, 2024
1cbeedd
build errors
catmcgee Feb 16, 2024
721dde8
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 16, 2024
18f9db8
Update docs/docs/developers/contracts/writing_contracts/storage/stora…
catmcgee Feb 19, 2024
0385c6c
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 19, 2024
d69e860
remove refernces to storage init
catmcgee Feb 19, 2024
c175552
update comuptue_note_hash_and_nullifier
catmcgee Feb 19, 2024
948c70c
Update docs/docs/developers/contracts/writing_contracts/functions/com…
catmcgee Feb 20, 2024
8ca8584
Update docs/docs/developers/tutorials/writing_token_contract.md
catmcgee Feb 26, 2024
fb8f6d7
Merge remote-tracking branch 'origin/master' into docs/note-type-ids
catmcgee Feb 26, 2024
2dfcd58
remove reference to compute_note_hash_and_nullifier
catmcgee Feb 26, 2024
b426332
note type ids fix confuding sentence
catmcgee Feb 26, 2024
505f5c4
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 26, 2024
be67ec3
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 27, 2024
7a4b593
update sidebar
catmcgee Feb 28, 2024
71acb9c
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 28, 2024
eea73bc
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 28, 2024
a20a7b6
clarifying note type ids
catmcgee Feb 29, 2024
bc943fd
updated note type references & storage struct stuff
catmcgee Feb 29, 2024
f5b63c4
Merge branch 'master' into docs/note-type-ids
catmcgee Feb 29, 2024
e0e8cf7
Merge branch 'master' into docs/note-type-ids
critesjosh Feb 29, 2024
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
496 changes: 63 additions & 433 deletions docs/docs/developers/contracts/references/storage/main.md

Large diffs are not rendered by default.

22 changes: 0 additions & 22 deletions docs/docs/developers/contracts/references/storage/public_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,34 +31,12 @@ Say that we wish to add `admin` public state variable into our storage struct. I

#include_code storage-leader-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust

And then when initializing it in the `Storage::init` function we can do:

#include_code storage-leader-init /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust

We have specified that we are storing a `Field` that should be placed in storage slot `1`. This is just a single value, and is similar to the following in solidity:

```solidity
address internal admin;
```

#### Mapping example

Say we want to have a group of `minters` that are able to mint assets in our contract, and we want them in public storage, because [access control in private is quite cumbersome](../../../../learn/concepts/communication/cross_chain_calls.md#a-note-on-l2-access-control). In the `Storage` struct we can add it as follows:

#include_code storage-minters-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust

And then when initializing it in the `Storage::init` function we can do it as follows:

#include_code storage-minters-init /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust

In this case, specifying that we are dealing with a map of Fields, and that it should be put at slot 2.

This would be similar to the following in solidity:

```solidity
mapping(address => bool) internal minters;
```

### `read`

On the `PublicState` structs we have a `read` method to read the value at the location in storage.
Expand Down
11 changes: 0 additions & 11 deletions docs/docs/developers/contracts/resources/common_patterns/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,6 @@ Hence, it's necessary to add a "randomness" field to your note to prevent such a

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

### Working with `compute_note_hash_and_nullifier()`

Currently, if you have storage defined, the compiler will error if you don't have a `compute_note_hash_and_nullifier()` defined. Without this, the PXE can't process encrypted events and discover your notes.

If your contract doesn't have anything to do with notes (e.g. operates solely in the public domain), you can do the following:
#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust

Otherwise, you need this method to help the PXE with processing your notes. In our [demo token contract](../../../tutorials/writing_token_contract.md#compute_note_hash_and_nullifier), we work with 2 kinds of notes: `ValueNote` and `TransparentNote`. Hence this method must define how to work with both:

#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust

### L1 -- L2 interactions

Refer to [Token Portal tutorial on bridging tokens between L1 and L2](../../../tutorials/token_portal/main.md) and/or [Uniswap tutorial that shows how to swap on L1 using funds on L2](../../../tutorials/uniswap/main.md). Both examples show how to:
Expand Down
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: How to define compute_note_hash_and_nullifier
---

Aztec will automatically compute and manage notes and nullifiers that are created in smart contracts. However, in some cases, it might make sense to write custom logic for how these are computed. This is achieved through the `compute_note_hash_and_nullifier()` function, which tells the [PXE](../../../../learn/concepts/pxe/main.md) how to handle notes in your smart contract.

## Params and returns

The function should take 5 parameters:

* Contract address
* Nonce
* Storage slot
* Note type ID
* Serialiazed note

It should return `pub [Field; 4]` which is an array of 4 elements that tells the PXE how to handle the notes and nullifiers:

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

## Placeholder

If you don't have any private state variables defined, you can use this placeholder function:

#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust
:::
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

## When using notes

If you are using custom notes or note types that come with Aztec.nr, you can call the util function `compute_note_hash_and_nulilfier` from the `aztec::utils` library in Aztec.nr. This will return the array needed.

This function takes:

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

Here is an example from the [token contract](../../../tutorials/writing_token_contract.md):

#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust

Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,12 @@ struct Storage {
}
```

:::danger
If your contract uses storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function to allow PXE to process encrypted events. See [encrypted events](../events/emit_event.md#successfully-process-the-encrypted-event) for more.

If you don't yet have any private state variables defined you can use this placeholder function:

#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust
:::

Since Aztec.nr is written in Noir, which is state-less, we need to specify how the storage struct should be initialized to read and write data correctly. This is done by specifying an `init` function that is run in functions that rely on reading or altering the state variables. This `init` function must declare the Storage struct with an instantiation defining how variables are accessed and manipulated. The function MUST be called `init` for the Aztec.nr library to properly handle it (this will be relaxed in the future).

```rust
impl Storage {
fn init(context: Context) -> Self {
Storage {
// (public state variables)::new()
// (private state variables)::new()
}
}
}
```

If you have defined a `Storage` struct following this naming scheme, then it will be made available to you through the reserved `storage` keyword within your contract functions.

:::warning Using slot `0` is not supported!
No storage values should be initialized at slot `0` - storage slots begin at `1`. This is a known issue that will be fixed in the future.
:::

:::danger
If your contract uses storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function to allow PXE to process encrypted events. See [how to implement compute_note_hash_and_nullifier()](../functions/compute_note_hash_and_nullifier.md) for more.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
:::
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,10 @@ Beware that this hash computation is what the aztec.nr library is doing, and not
With this note structure, the contract can require that only notes sitting at specific storage slots can be used by specific operations, e.g., if transferring funds from `from` to `to`, the notes to destroy should be linked to `H(map_slot, from)` and the new notes (except the change-note) should be linked to `H(map_slot, to)`.

That way, we can have logical storage slots, without them really existing. This means that knowing the storage slot for a note is not enough to actually figure out what is in there (whereas it would be for looking up public state).

## Note type IDs

The notion of `storage slots` helps enable a structured approach to data discovery and validation, but it does not allow a smart contract to hold multiple types of notes within one `Map`. This is because notes within a `Map` would get their own storage slot that is dynamically computed for each key.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

This has been solved with the concept of note type IDs. Each note type now has its own ID unique to its smart contract which tells the PXE how to handle it. If you are using your own custom `compute_note_hash_and_nullifier()` function, you must specify the note type ID. You can read more about that [here](../functions/compute_note_hash_and_nullifier.md).

Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Here, we are asserting that the `msg_sender()` is equal to the admin stored in p

## compute_note_hash_and_nullifier

Every Aztec contract that has storage must have a `compute_note_hash_and_nullifier()` function. If you try to compile without this function, you will get an error. This is explained in more detail [here](../contracts/resources/common_patterns/main.md#working-with-compute_note_hash_and_nullifier).
Every Aztec contract that has storage must have a `compute_note_hash_and_nullifier()` function. If you try to compile without this function, you will get an error. This is explained in more detail [here](../contracts/writing_contracts/functions/compute_note_hash_and_nullifier.md).

At the end of the contract, paste this:

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/developers/tutorials/writing_token_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Aztec transactions can pass data to Ethereum contracts through the rollup via th

Unconstrained functions can be thought of as view functions from Solidity--they only return information from the contract storage or compute and return data without modifying contract storage.

The `compute_note_hash_and_nullifier` function allows contract devs to specify how to compute notes and nullifiers. This must be included in every contract because it depends on the storage slots, which are defined when we set up storage.
The `compute_note_hash_and_nullifier` function allows contract devs to specify how to compute notes and nullifiers. This must be included in every contract because it depends on the note type ID and storage slots, which are defined when we set up storage. You can learn more about storage slot and note type IDs [here](../contracts/writing_contracts/storage/storage_slots.md).
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

## Contract dependencies

Expand Down Expand Up @@ -439,7 +439,7 @@ A getter function for checking the public balance of the provided Aztec account.

A getter function to compute the note hash and nullifier for notes in the contract's storage.

This must be included in every contract because it depends on the storage slots, which are defined when we set up storage.
This must be included in every contract because it depends on the note type IDs and storage slots, which are defined when we set up storage.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/aztec/src/note/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ pub fn compute_note_hash_for_consumption<Note, N>(note: Note) -> Field where Not
}

pub fn compute_note_hash_and_nullifier<T, N, S>(
// docs:start:compute_note_hash_and_nullifier_args
deserialize_content: fn([Field; N]) -> T,
note_header: NoteHeader,
serialized_note: [Field; S]
serialized_note: [Field; S] // docs:end:compute_note_hash_and_nullifier_args
) -> [Field; 4] where T: NoteInterface<N> {
let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));
// TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed
Expand All @@ -96,6 +97,7 @@ pub fn compute_note_hash_and_nullifier<T, N, S>(
let unique_siloed_note_hash = compute_unique_hash(note_header.nonce, siloed_note_hash);

let inner_nullifier = note.compute_nullifier_without_context();

// docs:start:compute_note_hash_and_nullifier_returns
[inner_note_hash, siloed_note_hash, unique_siloed_note_hash, inner_nullifier]
// docs:end:compute_note_hash_and_nullifier_returns
}
Loading