Skip to content

Commit

Permalink
refactor: move storage into main.nr. (#2068)
Browse files Browse the repository at this point in the history
Closes #1877 

# Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if
the PR is ready to merge.
- [ ] If the pull request requires a cryptography review (e.g.
cryptographic algorithm implementations) I have added the 'crypto' tag.
- [ ] I have reviewed my diff in github, line by line and removed
unexpected formatting changes, testing logs, or commented-out code.
- [ ] Every change is related to the PR description.
- [ ] I have
[linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
this pull request to relevant issues (if any exist).
  • Loading branch information
LeilaWang authored Sep 7, 2023
1 parent 2226091 commit 2c2d72b
Show file tree
Hide file tree
Showing 44 changed files with 731 additions and 944 deletions.
7 changes: 3 additions & 4 deletions docs/docs/dev_docs/contracts/layout.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
# Layout

## Directory structure

Here's a common layout for a basic Noir Contract project:

``` title="layout of an aztec contract project"
```title="layout of an aztec contract project"
─── my_aztec_contract_project
├── src
│ ├── main.nr <-- your contract
│ └── storage.nr <-- state variable declarations (by convention)
└── Nargo.toml <-- package and dependency management
```


> See the vanilla Noir docs for [more info on packages](https://noir-lang.org/modules_packages_crates/crates_and_packages).
> See the vanilla Noir docs for [more info on packages](https://noir-lang.org/modules_packages_crates/crates_and_packages).
3 changes: 0 additions & 3 deletions docs/docs/dev_docs/contracts/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,10 @@ There are a number of tools to make writing Noir Contracts more pleasant. See [h
Starter kit
:::


## Example Noir Contract

In keeping with the origins of blockchain, here's an example of a simple private token contract. Everyone's balances are private.

#include_code easy_private_token_storage /yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/storage.nr rust

#include_code easy_private_token_contract /yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr rust

:::info Disclaimer
Expand Down
18 changes: 11 additions & 7 deletions docs/docs/dev_docs/contracts/state_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Public state is persistent state that is _publicly visible_ to anyone in the wor
For developers coming from other blockchain ecosystems (such as Ethereum), this will be a familiar concept, because there, _all_ state is _publicly visible_.

Aztec public state follows an account-based model. That is, each state occupies a leaf in an account-based merkle tree: the _public state tree_ (INSERT LINK HERE). See _here_ (INSERT LINK HERE) for more of the technical details.

<!-- TODO: Insert links in the italics above -->

The `PublicState<T, T_SERIALISED_LEN>` struct serves as a wrapper around conventional Noir types `T`, allowing these types to be written to and read from the public state tree.
Expand All @@ -19,11 +20,11 @@ To declare a type `T` as a persistent, public state variable, use the `PublicSta

In the following example, we define a public state with a boolean type:

#include_code state_vars-PublicState /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-PublicState /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

The BoolSerialisationMethods is part of the Aztec stdlib:

#include_code state_vars-PublicStateBoolImport /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-PublicStateBoolImport /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

It contains methods that instruct its PublicState wrapper how to serialise and deserialise a boolean to and from a Field, which is the data type being saved in the public state tree.

Expand All @@ -47,7 +48,7 @@ First, define how to serialise and deserialise the custom type:

And then initialise the PublicState with it:

#include_code state_vars-PublicStateCustomStruct /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-PublicStateCustomStruct /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

### `.read`

Expand Down Expand Up @@ -92,9 +93,11 @@ For example, the following function calls the account contract before it updates
In contrast to public state, private state is persistent state that is _not_ visible to the whole world. Depending on the logic of the smart contract, a _private_ state variable's current value will only be known to one entity, or a closed group of entities.

The value of a private state variable can either be shared via an _encrypted log_ (INSERT_LINK_HERE), or offchain via web2, or completely offline: it's up to the app developer.

<!-- TODO: insert link in italics above -->

Aztec private state follows a utxo-based model. That is, a private state's current value is represented as one or many [notes](#notes). Each note is stored as an individual leaf in a utxo-based merkle tree: the _private state tree_ (INSERT_LINK_HERE).

<!-- TODO: insert link in italics above -->

To greatly simplify the experience of writing private state, Aztec.nr provides three different types of private state variable:
Expand Down Expand Up @@ -140,7 +143,7 @@ Singleton is a private state variable that is unique in a way. When a Singleton

Here we define a Singleton for storing a `CardNote`:

#include_code state_vars-Singleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-Singleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

### `.initialise`

Expand Down Expand Up @@ -178,7 +181,7 @@ ImmutableSingleton represents a unique private state variable that, as the name

In the following example, we define an ImmutableSingleton that utilises the `RulesMethods` struct as its underlying note type:

#include_code state_vars-ImmutableSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-ImmutableSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

### `.initialise`

Expand Down Expand Up @@ -208,7 +211,7 @@ The `new` method creates a Set that employs a specific note type. When a new Set

In the following example, we define a set whose underlying note type is `CardNote`:

#include_code state_vars-Set /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-Set /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

### `.insert`

Expand All @@ -231,6 +234,7 @@ This function returns the notes the account has access to:
#include_code state_vars-SetGet /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust

There's a limit on the maxinum number of notes this function can return at a time. Check _here_ (INSERT_LINK_HERE) and look for `MAX_READ_REQUESTS_PER_CALL` for the up-to-date number.

<!-- TODO: insert link in italics above -->

Because of this limit, we should always consider using the second argument `NoteGetterOptions` to target the notes we need, and to reduce the time required to recursively call this function.
Expand Down Expand Up @@ -291,7 +295,7 @@ The process of applying the options to get the final notes is not constrained. I

The following declares a mapping from a `Field` to a `Singleton`:

#include_code state_vars-MapSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code state_vars-MapSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

The second argument `|slot| Singleton::new(slot, ProfileMethods)` is a Noir closure function. It teaches this instance of `Map` how to create a new instance of a `Singleton` whenever the `.at` method is called to access a state variable at a particular mapping key. The `slot` argument will be derived when `.at` is called, based on the lookup key provided.

Expand Down
10 changes: 2 additions & 8 deletions docs/docs/dev_docs/contracts/storage.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
# Storage

> A common convention in Noir Contracts is to declare the state variables for your Noir Contract in a `storage.nr` file inside your project (see [directory structure](./layout.md#directory-structure)). This is just a convention, though: your contract would still work if you declare storage in the `main.nr` file.
State variables must be declared inside a struct. (This enables us to declare types composed of nested generics in Noir - see [types](./types.md)).

We could define any kinds of state variables in the Storage struct:

#include_code storage-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust
#include_code storage-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

See [State Variables](./state_variables.md) for how to initialise them.

Using Storage in a contract is like using any other struct in Noir. First, import the struct into the contract's `main.nr` file:

#include_code storage-import /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust

For each function that needs access to the storage, initialise the storage inside the function, and call the state variables in it:
Using Storage in a contract is like using any other struct in Noir. For each function that needs access to the storage, initialise the storage inside the function, and then access its state variable members:

#include_code storage-init /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
mod storage;

// A contract used along with `Parent` contract to test nested calls.
contract Child {
use crate::storage::Storage;
use dep::std::option::Option;

use dep::aztec::{
abi::CallContext,
context::{PrivateContext, PublicContext},
oracle::{
logs::emit_unencrypted_log,
compute_selector::compute_selector,
}
},
state_vars::public_state::PublicState,
types::type_serialisation::field_serialisation::{FieldSerialisationMethods, FIELD_SERIALISED_LEN},
};
use dep::std::option::Option;

struct Storage {
current_value: PublicState<Field, FIELD_SERIALISED_LEN>,
}

impl Storage {
fn init(
private_context: Option<&mut PrivateContext>,
public_context: Option<&mut PublicContext>,
) -> pub Self {
Storage {
current_value: PublicState::new(
private_context,
public_context,
1,
FieldSerialisationMethods,
),
}
}
}

#[aztec(private)]
fn constructor() {}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,22 +1,88 @@
mod account_contract_interface;
mod actions;
mod options;
mod storage;
mod types;

contract DocsExample {
use dep::std::option::Option;
use dep::aztec::{
context::{PrivateContext, PublicContext},
state_vars::{
immutable_singleton::ImmutableSingleton, map::Map, public_state::PublicState, set::Set,
singleton::Singleton,
},
};
// docs:start:state_vars-PublicStateBoolImport
use dep::aztec::types::type_serialisation::bool_serialisation::{
BoolSerialisationMethods, BOOL_SERIALISED_LEN,
};
// docs:end:state_vars-PublicStateBoolImport
use crate::account_contract_interface::AccountContractInterface;
use crate::actions;
use crate::options::{create_account_card_getter_options, create_largest_account_card_getter_options};
// docs:start:storage-import
use crate::storage::Storage;
// docs:end:storage-import
use crate::types::{
card_note::CardNote,
queen::Queen,
rules_note::RulesNote,
card_note::{CardNote, CardNoteMethods, CARD_NOTE_LEN},
profile_note::{ProfileNote, ProfileNoteMethods, PROFILE_NOTE_LEN},
queen::{Queen, QueenSerialisationMethods, QUEEN_SERIALISED_LEN},
rules_note::{RulesNote, RulesNoteMethods, RULES_NOTE_LEN},
};
use dep::std::option::Option;

// docs:start:storage-declaration
struct Storage {
locked: PublicState<bool, BOOL_SERIALISED_LEN>,
queen: PublicState<Queen, QUEEN_SERIALISED_LEN>,
game_rules: ImmutableSingleton<RulesNote, RULES_NOTE_LEN>,
legendary_card: Singleton<CardNote, CARD_NOTE_LEN>,
cards: Set<CardNote, CARD_NOTE_LEN>,
profiles: Map<Singleton<ProfileNote, PROFILE_NOTE_LEN>>,
}

// docs:start:state_vars-PublicState
// docs:start:state_vars-PublicStateCustomStruct
// docs:start:state_vars-Singleton
// docs:start:state_vars-ImmutableSingleton
// docs:start:state_vars-Set
// docs:start:state_vars-MapSingleton
impl Storage {
fn init(
private_context: Option<&mut PrivateContext>,
public_context: Option<&mut PublicContext>,
) -> pub Self {
Storage {
// highlight-next-line:state_vars-PublicState
locked: PublicState::new(private_context, public_context, 1, BoolSerialisationMethods),
// highlight-next-line:state_vars-PublicStateCustomStruct
queen: PublicState::new(
private_context,
public_context,
2,
QueenSerialisationMethods,
),
// highlight-next-line:state_vars-ImmutableSingleton
game_rules: ImmutableSingleton::new(private_context, 3, RulesNoteMethods),
// highlight-next-line:state_vars-Singleton
legendary_card: Singleton::new(private_context, public_context, 4, CardNoteMethods),
// highlight-next-line:state_vars-Set
cards: Set::new(private_context, public_context, 5, CardNoteMethods),
// highlight-next-line:state_vars-MapSingleton
profiles: Map::new(
private_context,
public_context,
6,
|private_context, public_context, slot| {
Singleton::new(private_context, public_context, slot, ProfileNoteMethods)
},
),
}
}
}
// docs:end:state_vars-PublicState
// docs:end:state_vars-PublicStateCustomStruct
// docs:end:state_vars-Singleton
// docs:end:state_vars-ImmutableSingleton
// docs:end:state_vars-Set
// docs:end:state_vars-MapSingleton
// docs:end:storage-declaration

global REPLACE_QUEEN_FUNCTION_SELECTOR = 11111111;
global GET_POINTS_OF_COMMON_CARD_FUNCTION_SELECTOR = 11111111;
Expand Down

This file was deleted.

Loading

0 comments on commit 2c2d72b

Please sign in to comment.