From 824221021cfad9fd8ee53beb61ecc44ef0aa0344 Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Tue, 22 Aug 2023 11:56:31 +0000 Subject: [PATCH] Docs for storage and state variables. --- docs/docs/dev_docs/contracts/functions.md | 10 +- .../dev_docs/contracts/state_variables.md | 219 ++++++++++++++++-- docs/docs/dev_docs/contracts/storage.md | 14 +- docs/docs/dev_docs/contracts/syntax.md | 12 +- yarn-project/noir-contracts/.gitignore | 2 +- .../docs_example_contract/Nargo.toml | 8 + .../docs_example_contract/src/actions.nr | 176 ++++++++++++++ .../docs_example_contract/src/main.nr | 199 ++++++++++++++++ .../docs_example_contract/src/options.nr | 66 ++++++ .../docs_example_contract/src/storage.nr | 50 ++++ .../src/storage/cards.nr | 9 + .../src/storage/game_rules.nr | 9 + .../src/storage/legendary_card.nr | 9 + .../src/storage/locked.nr | 11 + .../src/storage/profiles.nr | 12 + .../src/storage/queen.nr | 29 +++ .../docs_example_contract/src/types.nr | 4 + .../docs_example_contract/src/types/card.nr | 101 ++++++++ .../src/types/profile.nr | 88 +++++++ .../docs_example_contract/src/types/queen.nr | 6 + .../docs_example_contract/src/types/rules.nr | 84 +++++++ .../private_token_contract/src/main.nr | 2 - .../private_token_contract/src/storage.nr | 4 - .../public_token_contract/src/storage.nr | 5 +- .../noir-aztec/src/note/note_interface.nr | 2 + 25 files changed, 1090 insertions(+), 41 deletions(-) create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/Nargo.toml create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/cards.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/game_rules.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/legendary_card.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/locked.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/profiles.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/queen.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr create mode 100644 yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules.nr diff --git a/docs/docs/dev_docs/contracts/functions.md b/docs/docs/dev_docs/contracts/functions.md index e76052ffeb17..97993921d441 100644 --- a/docs/docs/dev_docs/contracts/functions.md +++ b/docs/docs/dev_docs/contracts/functions.md @@ -4,16 +4,20 @@ - A special `constructor` function MUST be declared within a contract's scope. - A constructor doesn't have a name, because its purpose is clear: to initialise state. -- In Aztec terminology, a constructor is always a 'private function' (i.e. it cannot be an `open` function). +- In Aztec terminology, a constructor is always a 'secret function' (i.e. it cannot be an `open` function). - A constructor behaves almost identically to any other function. It's just important for Aztec to be able to identify this function as special: it may only be called once, and will not be deployed as part of the contract. ## secret functions +#include_code functions-SecretFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust + ## `open` functions -## `unconstrained` functions +#include_code functions-OpenFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust +## `unconstrained` functions +#include_code functions-UncontrainedFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust # Calling functions @@ -47,4 +51,4 @@ E.g. `get()` ## Delegatecall -Talk a about the dangers of delegatecall too! \ No newline at end of file +Talk a about the dangers of delegatecall too! diff --git a/docs/docs/dev_docs/contracts/state_variables.md b/docs/docs/dev_docs/contracts/state_variables.md index bf7f46723edd..7a0584d02dd0 100644 --- a/docs/docs/dev_docs/contracts/state_variables.md +++ b/docs/docs/dev_docs/contracts/state_variables.md @@ -1,35 +1,220 @@ # State Variables -## `PublicState` +State variables come in two flavours: [**public** state](#publicstatet-t_serialised_len) and [**private** state](#private-state-variables). -Public state is persistent state which is _publicly visible_, by anyone in the world. +## `PublicState` -For developers coming from other blockchain ecosystems (such as Ethereum) this will be a familiar concept, because there, _all_ state is _publicly visible_. +Public state is persistent state that is _publicly visible_ to anyone in the world. -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_ (LINK). See here (LINK) for more of the technical details. +For developers coming from other blockchain ecosystems (such as Ethereum), this will be a familiar concept, because there, _all_ state is _publicly visible_. -The `PublicState` struct, provides a wrapper around conventional Noir types `T`, allowing such types to be written-to and read-from the public state tree. +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_ (LINK). See here (LINK) for more of the technical details. -#include_code PublicState /yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr rust +The `PublicState` struct serves as a wrapper around conventional Noir types `T`, allowing these types to be written to and read from the public state tree. -:::danger TODO -Examples which: -- initialise a `PublicState` by itself (without being wrapped in a `Map`) -- initialise a `PublicState` where `T` is a custom struct. -::: +The Aztec stdlib provides serialization methods for some common types. Check [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation) for the complete list. +### `::new` -## `Map` +In the following example, we define a public state with a boolean value. + +#include_code state_vars-PublicState /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/locked.nr rust + +### Custom value + +It's possible to create a public state for any types. For example, to create a public state for the following struct: + +#include_code state_vars-CustomStruct /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr rust + +First, define how to serialise and deserialise the struct. And then initialise the PublicState with it: + +#include_code state_vars-PublicStateCustomStruct /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/queen.nr rust + +### `.write` + +We can pass the associated type directly to a public state. It knows how to serialise the given value to store in the public state tree. + +#include_code state_vars-PublicStateWrite /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust +#include_code state_vars-PublicStateWriteCustom /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +### `.read` + +Reading a value from a public state is straightforward: +#include_code state_vars-PublicStateRead /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust -## Private State +It returns the type the public state was declared with. The above example returns a boolean. And the following example returns a custom struct. -### UTXO trees +#include_code state_vars-PublicStateReadCustom /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +## Private State Variables + +There are 3 different types of private state variables: + +- [Singleton](#singletonnotetype) +- [ImmutableSingleton](#immutablesingletonnotetype) +- [Set](#setnotetype) + +In contrast to public state variables, private state variables are only visible to specific relevant parties. The value of a private state variable can either be shared via (log)[INSERT_LINK_HERE] or completely offline. + +Note that an app can choose to emit the data via unencrypted log, or define a note whose data is easy to figure out, then the information is technically not private and could be visible to anyone. ### Notes -### Custom Notes +Unlike public state variables, which can be arbitrary types. Private state variables operate on `NoteType`. + +Notes are the fundamental elements in the private world. + +A note should confine to the following interface: + +#include_code NoteInterface /yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr rust + +## `Singleton` + +Singleton is a private state variable that is unique in a way. When a singleton is initialised, a note is created to represent its value. And the way to update the value is to destroy the current note, and create a new one with the updated value. + +### `::new` + +Here we define a singleton for storing a Card note: + +#include_code state_vars-Singleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/legendary_card.nr rust + +### `.initialise` + +The initial value of a singleton is set via calling `initialise`: + +#include_code state_vars-SingletonInit /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +When this function is called, a nullifier of the storage slot is created, preventing this singleton from being initialised again. + +### `.replace` + +To modify the value of a singleton, we will create a note (a Card in the following example) that has the new data, and replace the current note with it: + +#include_code state_vars-SingletonReplace /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +This function will destroy the old note under the hood. If two people are trying to modify the singleton at the same time, only one will succeed. + +### `.get_note` + +This function allows us to get the note of a singleton: + +#include_code state_vars-SingletonGet /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +However, it's possible that at the time this function is called, the system hasn't synched to the block where the latest note was created. Or a malicious user might feed an old state to this function, tricking the proving system into thinking that the value hasn't changed. To avoid an attack around it, this function will destroy the current note, and replace it with a duplicated note that has the same fields. Because the nullifier of the latest note will be emitted, if two people are trying to use this function against the same note, only one will succeed. + +## `ImmutableSingleton` + +Immutable singleton is unique and, as the name suggests, immutable. Once it has been initialised, its value can't be changed anymore. + +### `::new` + +#include_code state_vars-ImmutableSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/game_rules.nr rust + +### `.initialise` + +#include_code state_vars-ImmutableSingletonInit /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +### `.get_note` + +#include_code state_vars-ImmutableSingletonGet /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +Different to singleton, calling the `get_note` function on an immutable singleton to read the value doesn't destroy the current note behind the scene. Which means this function can be called simultaneously. + +## `Set` + +Set is used for managing a collection of notes. All notes in a set should be the same type. But whether they belong to one single account, or are accessible by different entities, is totally up to the developer. + +### `::new` + +In the following example, we define a set of cards: + +#include_code state_vars-Set /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/cards.nr rust + +### `.insert` + +We can call `insert` for as many times as we need to add new notes to a set: + +#include_code state_vars-SetInsert /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +### `.remove` + +We can also remove a note from a set: + +#include_code state_vars-SetRemove /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +Note that the transaction won't fail if the note we are removing does not exist in the set. As a best practice, we should fetch the notes by calling [`get_notes`](#get_notes), which does a membership check under the hood to make sure the notes exist, and then feed the returned notes to the `remove` function. + +### `.get_notes` + +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. + +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. + +### NoteGetterOptions + +`NoteGetterOptions` encapsulates a set of configurable options for retrieving notes from a database: + +#include_code NoteGetterOptions /yarn-project/noir-libs/noir-aztec/src/note/note_getter_options.nr rust + +For example, the following configs let us find the cards that belong to `account_address`. The returned cards are sorted by their points in descending order, and the first `offset` cards with the highest points are skipped. + +#include_code state_vars-NoteGetterOptionsSelectSortOffset /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr rust + +The first value of `.select` and `.sort` is the index of a field in a note type. For the note type `Card` that has the following fields: + +#include_code state_vars-NoteCard /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card.nr rust + +The indices are: 0 for `points`, 1 for `secret`, and 2 for `owner`. + +In the previous example, + +`.select(2, account_address)` matches the 2nd field of `Card`, which is `owner`, and returns the cards whose `owner` field equals `account_address`. + +`.sort(0, SortOrder.DESC)` sorts the 0th field of `Card`, which is `points`, in descending order. + +There can be as many conditions as the number of fields a note type has. The following example finds cards whose fields match the three given values: + +#include_code state_vars-NoteGetterOptionsMultiSelects /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr rust + +While `selects` lets us find notes with specific values, `filter` lets us find notes in a more dynamic way. The function below picks the cards whose points are at least `min_points`: + +#include_code state_vars-OptionFilter /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr rust + +We can use it as a filter to further reduce the number of the final notes: + +#include_code state_vars-NoteGetterOptionsFilter /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr rust + +One thing to remember is, `filter` will be applied on the notes after they are picked from the database. Therefor, it's possible that the actual notes we end up getting are fewer than the limit. + +The limit is `MAX_READ_REQUESTS_PER_CALL` by default. But we can set it to any value "smaller" than that: + +#include_code state_vars-NoteGetterOptionsPickOne /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr rust + +The process of applying the options to get the final notes is not constrained. It's necessary to always check the returned notes even when some conditions have been specified in the options. + +#include_code state_vars-check_return_notes /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust + +## `Map` + +`Map` is a state variable that maps a field to another state variable, which can be [`PublicState`](#publicstatet-t_serialised_len), all the [private state variables](#private-state-variables), and even another Map. + +### `::new` + +The following map uses singleton as its value: + +#include_code state_vars-MapSingleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/profiles.nr rust + +### `.at` + +The only api of a map is `.at`. It returns the underlying type that occupies a specific storage slot, which is generated by the field passed to `.at`. + +#include_code state_vars-MapAtSingletonInit /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust -### `UTXO` +#include_code state_vars-MapAtSingletonGet /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust -### `UTXOSet` \ No newline at end of file +In both code snippets, `state_var.at(account)` returns a singleton that is linked to the requested account. diff --git a/docs/docs/dev_docs/contracts/storage.md b/docs/docs/dev_docs/contracts/storage.md index 71a407f228cc..56f93b63c0b2 100644 --- a/docs/docs/dev_docs/contracts/storage.md +++ b/docs/docs/dev_docs/contracts/storage.md @@ -4,10 +4,16 @@ State variables must be declared inside a struct. (This enables us to declare types composed of nested generics in Noir - see [types](./types.md)). -By way of example, we could define a private state variable `balances`, mapping user addresses to their token balances: +We could define any kinds of state variables in the Storage struct: -#include_code storage-declaration /yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr rust +#include_code storage-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr rust -#include_code storage-import /yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr rust +See [State Variables](./state_variables.md) for how to initialise them. -State variables come in two flavours: **public** state and **private** state. . \ No newline at end of file +Using Storage in a contract is like using any other variables. First, import them to the `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: + +#include_code storage-init /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust diff --git a/docs/docs/dev_docs/contracts/syntax.md b/docs/docs/dev_docs/contracts/syntax.md index 288a46cb3806..132c5f2b780a 100644 --- a/docs/docs/dev_docs/contracts/syntax.md +++ b/docs/docs/dev_docs/contracts/syntax.md @@ -4,15 +4,15 @@ ## Aztec stdlib -On top of ['Vanialla Noir's' stdlib](https://noir-lang.org/standard_library/array_methods), we provide an [Aztec stdlib](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-libs) for writing Noir Contracts. The Aztec stdlib contains abstractions which remove the need to understand the low-level Aztec protocol. Notably, it provides: -- Public and private [state variable types](./types.md) +On top of ['Vanilla Noir's' stdlib](https://noir-lang.org/standard_library/array_methods), we provide an [Aztec stdlib](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-libs) for writing Noir Contracts. The Aztec stdlib contains abstractions which remove the need to understand the low-level Aztec protocol. Notably, it provides: + +- Public and private [state variable types](./types.md). - Ready-made notes. -- Functions for [emitting](./events.md) encrypted and unencrypted logs +- Functions for [emitting](./events.md) encrypted and unencrypted logs. - [Oracle functions](./functions.md#oracle-calls) for accessing: - private state - secrets -- Functions for communicating with Ethereum L1 - +- Functions for communicating with Ethereum L1. To import the Aztec stdlib into your Noir Contract project, simply include it as a dependency: @@ -20,4 +20,4 @@ To import the Aztec stdlib into your Noir Contract project, simply include it as https://github.com/AztecProtocol/aztec-packages/issues/1335 ::: -#include_code importing-aztec /yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml toml \ No newline at end of file +#include_code importing-aztec /yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml toml diff --git a/yarn-project/noir-contracts/.gitignore b/yarn-project/noir-contracts/.gitignore index 203ceefb7acb..983cade75af7 100644 --- a/yarn-project/noir-contracts/.gitignore +++ b/yarn-project/noir-contracts/.gitignore @@ -1,6 +1,6 @@ artifacts/ target/ proofs/ -types/ +/src/types/ Prover.toml Verifier.toml \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/docs_example_contract/Nargo.toml new file mode 100644 index 000000000000..add81444e03b --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "docs_example_contract" +authors = [""] +compiler_version = "0.1" +type = "contract" + +[dependencies] +aztec = { path = "../../../../noir-libs/noir-aztec" } \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr new file mode 100644 index 000000000000..a7103f2f78f2 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr @@ -0,0 +1,176 @@ +use dep::std::option::Option; +use dep::aztec::constants_gen::MAX_READ_REQUESTS_PER_CALL; +use dep::aztec::context::{ + PrivateContext, +}; +use dep::aztec::note::note_getter_options::NoteGetterOptions; +use dep::aztec::state_vars::{ + immutable_singleton::ImmutableSingleton, + map::Map, + public_state::PublicState, + set::Set, + singleton::Singleton, +}; +use dep::aztec::types::type_serialisation::bool_serialisation::{ + BOOL_SERIALISED_LEN, +}; + +use crate::storage::{ + queen::QUEEN_SERIALISED_LEN, +}; +use crate::types::{ + card::{Card, CARD_LEN}, + profile::{Profile, PROFILE_LEN}, + queen::Queen, + rules::{Rules, RULES_LEN}, +}; + +// docs:start:state_vars-PublicStateRead +fn is_locked(state_var: PublicState) -> bool { + state_var.read() +} +// docs:end:state_vars-PublicStateRead + +// docs:start:state_vars-PublicStateWrite +fn lock(state_var: PublicState) { + state_var.write(true); +} +// docs:end:state_vars-PublicStateWrite + +fn unlock(state_var: PublicState) { + state_var.write(false); +} + +// docs:start:state_vars-PublicStateReadCustom +fn get_current_queen(state_var: PublicState) -> Queen { + state_var.read() +} +// docs:end:state_vars-PublicStateReadCustom + +fn can_replace_queen( + state_var: PublicState, + new_queen: Queen, + ) -> bool { + let current_queen = get_current_queen(state_var); + new_queen.points > current_queen.points +} + +// docs:start:state_vars-PublicStateWriteCustom +fn replace_queen( + state_var: PublicState, + new_queen: Queen, +) { + state_var.write(new_queen); +} +// docs:end:state_vars-PublicStateWriteCustom + +// docs:start:state_vars-SingletonInit +fn init_legendary_card( + context: &mut PrivateContext, + state_var: Singleton, + card: &mut Card, +) { + state_var.initialise(context, card); +} +// docs:end:state_vars-SingletonInit + +// docs:start:state_vars-SingletonReplace +fn update_legendary_card( + context: &mut PrivateContext, + state_var: Singleton, + card: &mut Card, +) { + state_var.replace(context, card); +} +// docs:end:state_vars-SingletonReplace + +// docs:start:state_vars-SingletonGet +fn get_legendary_card( + context: &mut PrivateContext, + state_var: Singleton, +) -> Card { + state_var.get_note(context) +} +// docs:end:state_vars-SingletonGet + +// docs:start:state_vars-ImmutableSingletonInit +fn init_game_rules( + context: &mut PrivateContext, + state_var: ImmutableSingleton, + rules: &mut Rules, +) { + state_var.initialise(context, rules); +} +// docs:end:state_vars-ImmutableSingletonInit + +// docs:start:state_vars-ImmutableSingletonGet +fn is_valid_card( + context: &mut PrivateContext, + state_var: ImmutableSingleton, + card: Card, +) -> bool { + let rules = state_var.get_note(context); + card.points >= rules.min_points & card.points <= rules.max_points +} +// docs:end:state_vars-ImmutableSingletonGet + +// docs:start:state_vars-SetInsert +fn add_new_card( + context: &mut PrivateContext, + state_var: Set, + card: &mut Card, + ) { + state_var.insert(context, card); +} +// docs:end:state_vars-SetInsert + +// docs:start:state_vars-SetRemove +fn remove_card( + context: &mut PrivateContext, + state_var: Set, + card: Card, +) { + state_var.remove(context, card); +} +// docs:end:state_vars-SetRemove + +// docs:start:state_vars-SetGet +fn get_cards( + context: &mut PrivateContext, + state_var: Set, + options: NoteGetterOptions, +) -> [Option; MAX_READ_REQUESTS_PER_CALL] { + state_var.get_notes(context, options) +} +// docs:end:state_vars-SetGet + +// docs:start:state_vars-SetContains +fn assert_contains_card( + context: &mut PrivateContext, + state_var: Set, + card: Card, +) { + state_var.assert_contains_and_remove(context, card); +} +// docs:end:state_vars-SetContains + +// docs:start:state_vars-MapAtSingletonInit +fn add_new_profile( + context: &mut PrivateContext, + state_var: Map>, + account: Field, + profile: &mut Profile, +) { + state_var.at(account).initialise(context, profile); +} +// docs:end:state_vars-MapAtSingletonInit + +// docs:start:state_vars-MapAtSingletonGet +fn get_profile( + context: &mut PrivateContext, + state_var: Map>, + account: Field, +) -> Profile { + state_var.at(account).get_note(context) +} +// docs:end:state_vars-MapAtSingletonGet \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr new file mode 100644 index 000000000000..00cc73455898 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr @@ -0,0 +1,199 @@ +mod actions; +mod options; +mod storage; +mod types; + +contract DocsExample { + use dep::aztec::abi; + use dep::aztec::abi::{PrivateCircuitPublicInputs, PrivateContextInputs, PublicContextInputs}; + use dep::aztec::constants_gen::MAX_READ_REQUESTS_PER_CALL; + use dep::aztec::context::{ + PrivateContext, + PublicContext, + }; + + use crate::actions; + use crate::options::{create_get_account_cards_options, create_get_account_largest_card_options}; + // docs:start:storage-import + use crate::storage::Storage; + // docs:end:storage-import + use crate::types::{ + card::Card, + queen::Queen, + rules::Rules, + }; + + global REPLACE_QUEEN_FUNCTION_SELECTOR = 11111111; + global GET_POINTS_OF_COMMON_CARD_FUNCTION_SELECTOR = 11111111; + + fn constructor( + inputs: PrivateContextInputs, + min_points: u8, + max_points: u8, + legendary_card_secret: Field, + ) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, abi::hash_args([ + min_points as Field, + max_points as Field, + legendary_card_secret, + ])); + + let storage = Storage::init(); + + let mut game_rules = Rules::new(min_points, max_points); + actions::init_game_rules(&mut context, storage.game_rules, &mut game_rules); + + let mut legendary_card = Card::new(0, legendary_card_secret, 0); + actions::init_legendary_card(&mut context, storage.legendary_card, &mut legendary_card); + + context.finish() + } + + // docs:start:storage-init + open fn lock(inputs: PublicContextInputs) -> pub abi::PublicCircuitPublicInputs { + let context = PublicContext::new(inputs, 0); + + // highlight-next-line:storage-init + let storage = Storage::init(); + storage.locked.write(true); + + context.finish() + } + // docs:end:storage-init + + // docs:start:functions-OpenFunction + open fn unlock(inputs: PublicContextInputs) -> pub abi::PublicCircuitPublicInputs { + let context = PublicContext::new(inputs, 0); + + let storage = Storage::init(); + actions::unlock(storage.locked); + + context.finish() + } + // docs:end:functions-OpenFunction + + open fn replace_queen( + inputs: PublicContextInputs, + account: Field, + points: u8, + ) -> pub abi::PublicCircuitPublicInputs { + let context = PublicContext::new(inputs, abi::hash_args([account, points as Field])); + let storage = Storage::init(); + + let new_queen = Queen { account, points }; + + assert(actions::can_replace_queen(storage.queen, new_queen)); + + actions::replace_queen(storage.queen, new_queen); + + context.finish() + } + + // docs:start:functions-SecretFunction + fn add_common_cards( + inputs: PrivateContextInputs, + secrets: [Field; 4], + ) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, abi::hash_args(secrets)); + let storage = Storage::init(); + + for i in 0..secrets.len() as u8 { + let mut card = Card::new(0, secrets[i], 0); + actions::add_new_card(&mut context, storage.cards, &mut card); + } + + context.finish() + } + // docs:end:functions-SecretFunction + + fn update_legendary_card( + inputs: PrivateContextInputs, + new_points: u8, + new_secret: Field, + ) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, abi::hash_args([new_secret])); + let storage = Storage::init(); + + let owner = inputs.call_context.msg_sender; + let mut updated_card = Card::new(new_points, new_secret, owner); + + assert(actions::is_valid_card(&mut context, storage.game_rules, updated_card)); + + actions::update_legendary_card(&mut context, storage.legendary_card, &mut updated_card); + + context.finish() + } + + fn become_queen(inputs: PrivateContextInputs) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, 0); + let storage = Storage::init(); + + let legendary_card = actions::get_legendary_card(&mut context, storage.legendary_card); + + let owner = legendary_card.owner; + let result = context.call_private_function( + inputs.call_context.storage_contract_address, + GET_POINTS_OF_COMMON_CARD_FUNCTION_SELECTOR, + [owner, 0] + ); + let total_points = legendary_card.points + result[0] as u8; + + context.call_public_function( + inputs.call_context.storage_contract_address, + REPLACE_QUEEN_FUNCTION_SELECTOR, + [owner, total_points as Field] + ); + + context.finish() + } + + fn get_points_of_common_cards( + inputs: PrivateContextInputs, + account: Field, + offset: u32, + ) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, abi::hash_args([account, offset as Field])); + let storage = Storage::init(); + + let mut total_points = 0; + let options = create_get_account_cards_options(account, offset); + let cards = actions::get_cards(&mut context, storage.cards, options); + for i in 0..MAX_READ_REQUESTS_PER_CALL { + if (cards[i].is_some()) { + let card = cards[i].unwrap_unchecked(); + assert(card.owner == account); + total_points += card.points; + } + } + + context.return_values.push(total_points as Field); + + context.finish() + } + + // docs:start:state_vars-check_return_notes + fn discard_largest_card( + inputs: PrivateContextInputs, + ) -> distinct pub PrivateCircuitPublicInputs { + let mut context = PrivateContext::new(inputs, 0); + let storage = Storage::init(); + + let account = context.msg_sender(); + let options = create_get_account_largest_card_options(account); + let card = actions::get_cards(&mut context, storage.cards, options)[0].unwrap_unchecked(); + // highlight-next-line:state_vars-check_return_notes + assert(card.owner == account); + + actions::remove_card(&mut context, storage.cards, card); + + context.finish() + } + // docs:end:state_vars-check_return_notes + + // docs:start:functions-UncontrainedFunction + unconstrained fn get_total_points(account: Field) -> u8 { + // + 0 + } + // docs:end:functions-UncontrainedFunction +} diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr new file mode 100644 index 000000000000..2b31a632ef39 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/options.nr @@ -0,0 +1,66 @@ +use dep::std::option::Option; +use dep::aztec::constants_gen::MAX_READ_REQUESTS_PER_CALL; +use dep::aztec::note::note_getter_options::{NoteGetterOptions, Sort, SortOrder}; +use crate::types::card::{Card, CARD_LEN}; + +// docs:start:state_vars-NoteGetterOptionsSelectSortOffset +fn create_get_account_cards_options( + account_address: Field, + offset: u32, +) -> NoteGetterOptions { + NoteGetterOptions::new() + .select(2, account_address) + .sort(0, SortOrder.DESC) + .set_offset(offset) +} +// docs:end:state_vars-NoteGetterOptionsSelectSortOffset + +// docs:start:state_vars-NoteGetterOptionsMultiSelects +fn create_get_exact_card_options( + points: u8, + secret: Field, + account_address: Field, +) -> NoteGetterOptions { + NoteGetterOptions::new() + .select(0, points as Field) + .select(1, secret) + .select(2, account_address) +} +// docs:end:state_vars-NoteGetterOptionsMultiSelects + +// docs:start:state_vars-OptionFilter +fn filter_min_points( + cards: [Option; MAX_READ_REQUESTS_PER_CALL], + min_points: u8, +) -> [Option; MAX_READ_REQUESTS_PER_CALL] { + let mut selected_cards = [Option::none(); MAX_READ_REQUESTS_PER_CALL]; + let mut num_selected = 0; + for i in 0..cards.len() { + if cards[i].is_some() & cards[i].unwrap_unchecked().points >= min_points { + selected_cards[num_selected] = cards[i]; + num_selected += 1; + } + } + selected_cards +} +// docs:end:state_vars-OptionFilter + +// docs:start:state_vars-NoteGetterOptionsFilter +fn create_get_account_cards_with_min_points_options( + account_address: Field, + min_points: u8, +) -> NoteGetterOptions { + NoteGetterOptions::with_filter(filter_min_points, min_points) + .select(2, account_address) + .sort(0, SortOrder.ASC) +} +// docs:end:state_vars-NoteGetterOptionsFilter + +// docs:start:state_vars-NoteGetterOptionsPickOne +fn create_get_account_largest_card_options(account_address: Field) -> NoteGetterOptions { + NoteGetterOptions::new() + .select(2, account_address) + .sort(0, SortOrder.DESC) + .set_limit(1) +} +// docs:end:state_vars-NoteGetterOptionsPickOne \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr new file mode 100644 index 000000000000..0a0cce65b11c --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr @@ -0,0 +1,50 @@ +mod cards; +mod game_rules; +mod legendary_card; +mod locked; +mod profiles; +mod queen; + +use dep::aztec::state_vars::{ + immutable_singleton::ImmutableSingleton, + map::Map, + public_state::PublicState, + set::Set, + singleton::Singleton, +}; +use dep::aztec::types::type_serialisation::bool_serialisation::{ + BOOL_SERIALISED_LEN, +}; + +use crate::types::{ + card::{Card, CARD_LEN}, + profile::{Profile, PROFILE_LEN}, + queen::Queen, + rules::{Rules, RULES_LEN}, +}; + +use queen::QUEEN_SERIALISED_LEN; + +// docs:start:storage-declaration +struct Storage { + locked: PublicState, + queen: PublicState, + game_rules: ImmutableSingleton, + legendary_card: Singleton, + cards: Set, + profiles: Map>, +} + +impl Storage { + fn init() -> Self { + Storage { + locked: locked::init(1), + queen: queen::init(2), + game_rules: game_rules::init(3), + legendary_card: legendary_card::init(4), + cards: cards::init(5), + profiles: profiles::init(6), + } + } +} +// docs:end:storage-declaration \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/cards.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/cards.nr new file mode 100644 index 000000000000..62f5a517f254 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/cards.nr @@ -0,0 +1,9 @@ +// docs:start:state_vars-Set +use dep::aztec::state_vars::set::Set; + +use crate::types::card::{Card, CardMethods, CARD_LEN}; + +fn init(storage_slot: Field) -> Set { + Set::new(storage_slot, CardMethods) +} +// docs:end:state_vars-Set \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/game_rules.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/game_rules.nr new file mode 100644 index 000000000000..f037aa0ad4e0 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/game_rules.nr @@ -0,0 +1,9 @@ +// docs:start:state_vars-ImmutableSingleton +use dep::aztec::state_vars::immutable_singleton::ImmutableSingleton; + +use crate::types::rules::{Rules, RulesMethods, RULES_LEN}; + +fn init(storage_slot: Field) -> ImmutableSingleton { + ImmutableSingleton::new(storage_slot, RulesMethods) +} +// docs:end:state_vars-ImmutableSingleton \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/legendary_card.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/legendary_card.nr new file mode 100644 index 000000000000..dc85dd8220e1 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/legendary_card.nr @@ -0,0 +1,9 @@ +// docs:start:state_vars-Singleton +use dep::aztec::state_vars::singleton::Singleton; + +use crate::types::card::{Card, CardMethods, CARD_LEN}; + +fn init(storage_slot: Field) -> Singleton { + Singleton::new(storage_slot, CardMethods) +} +// docs:end:state_vars-Singleton \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/locked.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/locked.nr new file mode 100644 index 000000000000..efe4b1fbdafa --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/locked.nr @@ -0,0 +1,11 @@ +// docs:start:state_vars-PublicState +use dep::aztec::state_vars::public_state::PublicState; +use dep::aztec::types::type_serialisation::bool_serialisation::{ + BoolSerialisationMethods, + BOOL_SERIALISED_LEN, +}; + +fn init(storage_slot: Field) -> PublicState { + PublicState::new(storage_slot, BoolSerialisationMethods) +} +// docs:end:state_vars-PublicState \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/profiles.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/profiles.nr new file mode 100644 index 000000000000..635bf1ab5589 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/profiles.nr @@ -0,0 +1,12 @@ +// docs:start:state_vars-MapSingleton +use dep::aztec::state_vars::{ + map::Map, + singleton::Singleton, +}; + +use crate::types::profile::{Profile, ProfileMethods, PROFILE_LEN}; + +fn init(storage_slot: Field) -> Map> { + Map::new(storage_slot, |slot| Singleton::new(slot, ProfileMethods)) +} +// docs:end:state_vars-MapSingleton \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/queen.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/queen.nr new file mode 100644 index 000000000000..8d22dc26a388 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage/queen.nr @@ -0,0 +1,29 @@ +use dep::aztec::state_vars::public_state::PublicState; +use dep::aztec::types::type_serialisation::TypeSerialisationInterface; + +use crate::types::queen::Queen; + +// docs:start:state_vars-PublicStateCustomStruct +global QUEEN_SERIALISED_LEN: Field = 2; + +fn deserialise(fields: [Field; QUEEN_SERIALISED_LEN]) -> Queen { + Queen { + account: fields[0], + points: fields[1] as u8, + } +} + +fn serialise(queen: Queen) -> [Field; QUEEN_SERIALISED_LEN] { + [queen.account, queen.points as Field] +} + +global QueenSerialisationMethods = TypeSerialisationInterface { + deserialise, + serialise, +}; + +fn init(storage_slot: Field) -> PublicState { + // highlight-next-line:state_vars-PublicStateCustomStruct + PublicState::new(storage_slot, QueenSerialisationMethods) +} +// docs:end:state_vars-PublicStateCustomStruct \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types.nr new file mode 100644 index 000000000000..655418e559c8 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types.nr @@ -0,0 +1,4 @@ +mod card; +mod profile; +mod queen; +mod rules; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card.nr new file mode 100644 index 000000000000..cbf1ccada80f --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card.nr @@ -0,0 +1,101 @@ +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, +}; +use dep::aztec::oracle::{ + get_secret_key::get_secret_key, + get_public_key::get_public_key, +}; + +global CARD_LEN: Field = 3; + +// docs:start:state_vars-NoteCard +struct Card { + points: u8, + secret: Field, + owner: Field, + header: NoteHeader, +} +// docs:end:state_vars-NoteCard + +impl Card { + fn new(points: u8, secret: Field, owner: Field) -> Self { + Card { + points, + secret, + owner, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; CARD_LEN] { + [self.points as Field, self.secret, self.owner] + } + + fn deserialise(preimage: [Field; CARD_LEN]) -> Self { + Card { + points: preimage[0] as u8, + secret: preimage[1], + owner: preimage[2], + header: NoteHeader::empty(), + } + } + + fn compute_note_hash(self) -> Field { + dep::std::hash::pedersen([ + self.points as Field, + self.secret, + self.owner, + ])[0] + } + + fn compute_nullifier(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(CardMethods, self); + let owner_nullifying_public_key = get_public_key(self.owner); + // TODO: get_secret_key should just accept an address + // TODO! + let secret = get_secret_key(owner_nullifying_public_key); + dep::std::hash::pedersen([ + note_hash_for_nullify, + secret, + ])[0] + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } +} + +fn deserialise(preimage: [Field; CARD_LEN]) -> Card { + Card::deserialise(preimage) +} + +fn serialise(note: Card) -> [Field; CARD_LEN] { + note.serialise() +} + +fn compute_note_hash(note: Card) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: Card) -> Field { + note.compute_nullifier() +} + +fn get_header(note: Card) -> NoteHeader { + note.header +} + +fn set_header(note: &mut Card, header: NoteHeader) { + note.set_header(header) +} + +global CardMethods = NoteInterface { + deserialise, + serialise, + compute_note_hash, + compute_nullifier, + get_header, + set_header, +}; diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile.nr new file mode 100644 index 000000000000..a0e702ab7990 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile.nr @@ -0,0 +1,88 @@ +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, +}; +use dep::aztec::oracle::{ + get_secret_key::get_secret_key, + get_public_key::get_public_key, +}; + +global PROFILE_LEN: Field = 2; + +struct Profile { + avatar: Field, + xp: Field, + header: NoteHeader, +} + +impl Profile { + fn new(avatar: Field, xp: Field) -> Self { + Profile { + avatar, + xp, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; PROFILE_LEN] { + [self.avatar, self.xp] + } + + fn deserialise(preimage: [Field; PROFILE_LEN]) -> Self { + Profile { + avatar: preimage[1], + xp: preimage[0], + header: NoteHeader::empty(), + } + } + + fn compute_note_hash(self) -> Field { + dep::std::hash::pedersen([ + self.avatar, + self.xp, + ])[0] + } + + fn compute_nullifier(_self: Self) -> Field { + assert(false); // Not allowed. + 0 + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } +} + +fn deserialise(preimage: [Field; PROFILE_LEN]) -> Profile { + Profile::deserialise(preimage) +} + +fn serialise(note: Profile) -> [Field; PROFILE_LEN] { + note.serialise() +} + +fn compute_note_hash(note: Profile) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: Profile) -> Field { + note.compute_nullifier() +} + +fn get_header(note: Profile) -> NoteHeader { + note.header +} + +fn set_header(note: &mut Profile, header: NoteHeader) { + note.set_header(header) +} + +global ProfileMethods = NoteInterface { + deserialise, + serialise, + compute_note_hash, + compute_nullifier, + get_header, + set_header, +}; diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr new file mode 100644 index 000000000000..383a092269db --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr @@ -0,0 +1,6 @@ +// docs:start:state_vars-CustomStruct +struct Queen { + account: Field, + points: u8, +} +// docs:end:state_vars-CustomStruct \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules.nr new file mode 100644 index 000000000000..4c9565e53830 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules.nr @@ -0,0 +1,84 @@ +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, +}; + +global RULES_LEN: Field = 2; + +struct Rules { + min_points: u8, + max_points: u8, + header: NoteHeader, +} + +impl Rules { + fn new(min_points: u8, max_points: u8) -> Self { + Rules { + min_points, + max_points, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; RULES_LEN] { + [self.min_points as Field, self.max_points as Field] + } + + fn deserialise(preimage: [Field; RULES_LEN]) -> Self { + Rules { + min_points: preimage[0] as u8, + max_points: preimage[1] as u8, + header: NoteHeader::empty(), + } + } + + fn compute_note_hash(self) -> Field { + dep::std::hash::pedersen([ + self.min_points as Field, + self.max_points as Field, + ])[0] + } + + fn compute_nullifier(_self: Self) -> Field { + // Not used + 0 + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } +} + +fn deserialise(preimage: [Field; RULES_LEN]) -> Rules { + Rules::deserialise(preimage) +} + +fn serialise(note: Rules) -> [Field; RULES_LEN] { + note.serialise() +} + +fn compute_note_hash(note: Rules) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: Rules) -> Field { + note.compute_nullifier() +} + +fn get_header(note: Rules) -> NoteHeader { + note.header +} + +fn set_header(note: &mut Rules, header: NoteHeader) { + note.set_header(header) +} + +global RulesMethods = NoteInterface { + deserialise, + serialise, + compute_note_hash, + compute_nullifier, + get_header, + set_header, +}; diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr index 514377b95a81..f83de75a3d1f 100644 --- a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr @@ -17,9 +17,7 @@ contract PrivateToken { }; use dep::aztec::log::emit_unencrypted_log; - // docs:start:storage-import use crate::storage::Storage; - // docs:end:storage-import // docs:start:constructor // Constructs the contract and sets `initial_supply` which is fully owned by `owner`. diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr index 52fcd6914904..36e5fc8e9f40 100644 --- a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr @@ -8,14 +8,11 @@ use dep::value_note::value_note::{ VALUE_NOTE_LEN, }; -// docs:start:storage-declaration -// highlight-next-line:storage-declaration struct Storage { // maps an aztec address to its balance balances: Map>, } -// highlight-next-line:storage-declaration impl Storage { fn init() -> Self { Storage { @@ -23,4 +20,3 @@ impl Storage { } } } -// docs:end:storage-declaration diff --git a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr index 9513325c9fa4..ef39a851b2ef 100644 --- a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr @@ -1,4 +1,3 @@ -// docs:start:PublicState use dep::aztec::state_vars::{ map::Map, // highlight-start:PublicState @@ -12,7 +11,6 @@ use dep::aztec::types::type_serialisation::field_serialisation::{ }; struct Storage { - // highlight-next-line:PublicState balances: Map>, } @@ -22,5 +20,4 @@ impl Storage { balances: Map::new(1, |slot| PublicState::new(slot, FieldSerialisationMethods)), } } -} -// docs:end:PublicState \ No newline at end of file +} \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr b/yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr index fd662fc3b476..84d171fd5bae 100644 --- a/yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr +++ b/yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr @@ -1,5 +1,6 @@ use crate::note::note_header::NoteHeader; +// docs:start:NoteInterface struct NoteInterface { deserialise: fn ([Field; N]) -> Note, @@ -13,3 +14,4 @@ struct NoteInterface { set_header: fn (&mut Note, NoteHeader) -> (), } +// docs:end:NoteInterface \ No newline at end of file