diff --git a/docs/docs/dev_docs/contracts/functions.md b/docs/docs/dev_docs/contracts/functions.md index e76052ffeb1..ceddbeb1186 100644 --- a/docs/docs/dev_docs/contracts/functions.md +++ b/docs/docs/dev_docs/contracts/functions.md @@ -9,11 +9,19 @@ ## secret functions +> a.k.a. "private" functions + +#include_code functions-SecretFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust + ## `open` functions -## `unconstrained` functions +> a.k.a. "public" 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 +55,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 bf7f46723ed..14f5b794f07 100644 --- a/docs/docs/dev_docs/contracts/state_variables.md +++ b/docs/docs/dev_docs/contracts/state_variables.md @@ -1,35 +1,302 @@ # 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_](INSERT_LINK_HERE). See [here] (INSERT_LINK_HERE) 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. -::: +### `::new` +To declare a type `T` as a persistent, public state variable, use the `PublicState::new()` constructor. -## `Map` +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 + +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 + +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. + +The Aztec stdlib provides serialization methods for various 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. + +### Custom types + +It's possible to create a public state for any types. Simply define methods that guide the PublicState wrapper in serialising the custom type to field(s) to store in the public state tree, and deserialising the field(s) retrieved from the tree back to the custom type. + +The methods should be implemented in a struct that conforms to the following interface: + +#include_code TypeSerialisationInterface /yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr rust + +For example, to create a public state for the following type: + +#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 custom type: + +#include_code state_vars-PublicStateCustomStruct /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr rust + +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 + +### `.read` + +Reading the currently-stored value of a public state variable is straightforward: + +#include_code state_vars-PublicStateRead /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +It returns the type the public state was declared with. The above example returns a boolean. And the following example returns a custom struct. + +#include_code state_vars-PublicStateReadCustom /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +Every public state can be read before its value is written. The default value is 0, or { 0, 0, ... } if it's a struct. + +### `.write` + +The currently-stored value of a private state variable can be overwritten with `.write()`. + +Due to the way public states are [declared](#new), a public state knows how to serialise a given value and store it in the protocol's public state tree. + +We can pass the associated type directly to the `write()` method: + +#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 and write + +A common pattern is reading a public state, changing the value, and then writing the new value back to the public state. Remember to always call `.write` to update the value. The value of a public state won't be changed by modifying the return value of `.read`. + +#include_code state_vars-PublicStateReadWriteCustom /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +#### Writing before calling + +**Important note:** +Before making a call to an external function, it is important to remember to `.write` state variables that have been edited, so as to persist their new values. This is particularly important if the call to the external function might result in re-entrancy into your contract, later in the transaction. If state variables aren't written before making such an external call, then upon re-entrancy, the 'current values' of your state variables will equal the values as at the start of the original function call. + +For example, the following function calls the account contract before it updates the public state. This allows the account contract, which can have arbitrary logic defined by the account itself, to call back to this function within its `send_rewards` function. And because this function hasn't updated the public state, the conditions are still true. This means `send_rewards` will be triggered again and again. +#include_code state_vars-PublicStateWriteBeforeCall /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust -## Private State +## Private State Variables -### UTXO trees +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. + +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). + +To greatly simplify the experience of writing private state, Aztec.nr provides three different types of private state variable: + +- [Singleton](#singletonnotetype) +- [ImmutableSingleton](#immutablesingletonnotetype) +- [Set](#setnotetype) + +These three structs abstract-away many of Aztec's protocol complexities, by providing intuitive methods to modify notes in the utxo tree in a privacy-preserving way. + +> Note that an app can also choose to emit data via unencrypted log, or to 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 conform to the following interface: + +#include_code NoteInterface /yarn-project/noir-libs/noir-aztec/src/note/note_interface.nr rust + +The interplay between a private state variable and its notes can be confusing. Here's a summary to aid intuition: + +- A private state variable (of type `Singleton`, `ImmutableSingleton` or `Set`) may be declared in [Storage](./storage.md). +- Every note contains (as a 'header') the contract address and storage slot of the state variable to which it "belongs". A note is said to "belong" to a private state if the storage slot of the private state matches the storage slot contained in the note's header. + - Management of this 'header' is abstracted-away from developers who use the `ImmutableSingleton`, `Singleton` and `Set` types. +- A private state variable is colloquially said to "point" to one or many notes (depending on the type), if those note(s) all "belong" to that private state, and those note(s) haven't-yet been nullified. +- An `ImmutableSingleton` will point to _one_ note over the lifetime of the contract. ("One", hence "Singleton"). This note is a struct of information that is persisted forever. +- A `Singleton` may point to _one_ note at a time. ("One", hence "Singleton"). But since it's not "immutable", the note that it points to may be [replaced](#replace) by functions of the contract, over time. The "current value" of a `Singleton` is interpreted as the one note which has not-yet been nullified. The act of 'replacing' a Singleton's note is how a `Singleton` state may be modified by functions. + - `Singleton` is a useful type when declaring a private state which may only ever be modified by those who are privy to the current value of that state. +- A `Set` may point to _multiple_ notes at a time. The "current value" of a private state variable of type `Set` is some 'accumulation' of all not-yet nullified notes which "belong" to the `Set`. + - The term "some accumulation" is intentionally vague. The interpretation of the "current value" of a `Set` must be expressed by the smart contract developer. A common use case for a `Set` is to represent the sum of a collection of values (in which case 'accumulation' is 'summation'). + - Think of a ZCash balance (or even a Bitcoin balance). The "current value" of a user's ZCash balance is the sum of all unspent (not-yet nullified) notes belonging to that user. + - To modify the "current value" of a `Set` state variable, is to [`insert`](#insert) new notes into the `Set`, or [`remove`](#remove) notes from that set. + - Interestingly, if a developer requires a private state to be modifiable by users who _aren't_ privy to the value of that state, a `Set` is a very useful type. The `insert` method allows new notes to be added to the `Set` without knowing any of the other notes in the set! (Like posting an envelope into a post box, you don't know what else is in there!). + +## `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 `CardNote`: + +#include_code state_vars-Singleton /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.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. + +Unlike public states, which have a default initial value of `0` (or many zeros, in the case of a struct, array or map), a private state (of type `Singleton`, `ImmutableSingleton` or `Set`) does not have a default initial value. The `initialise` method (or `insert`, in the case of a `Set`) must be called. + +### `.replace` + +The 'current value' of a `Singleton` state variable may be overwritten via the `.replace` method. + +To modify the 'current value' of a Singleton, we may create a new note (a `CardNote` in the following example) containing some 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. Developers should put in place appropriate access controls to avoid race conditions (unless a race is intended!). + +### `.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` + +ImmutableSingleton represents a unique private state variable that, as the name suggests, is immutable. Once initialized, its value cannot be altered. + +### `::new` + +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 + +### `.initialise` + +Set the initial value of an ImmutableSingleton by calling the `initialise` method: + +#include_code state_vars-ImmutableSingletonInit /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +Once initialized, an ImmutableSingleton's value remains unchangeable. This method can only be called once. + +### `.get_note` + +Use this method to retrieve the value of an initialized ImmutableSingleton: + +#include_code state_vars-ImmutableSingletonGet /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr rust + +Unlike a [`singleton`](#get_note-1), the `get_note` function for an ImmutableSingleton doesn't destroy the current note in the background. This means that multiple accounts can concurrently call this function to read the value. + +This function will throw if the ImmutableSingleton hasn't been initialised. + +## `Set` + +Set is used for managing a collection of notes. All notes in a set are of the same `NoteType`. But whether these notes all belong to one entity, or are accessible and editable by different entities, is totally up to the developer. + +### `::new` + +The `new` method creates a Set that employs a specific note type. When a new Set is created, it initially contains no notes. + +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 + +### `.insert` + +We can call `insert` for as many times as we need to add new notes to a `Set`. A `Set` is unbounded in size. + +#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 filtering and retrieving a selection of notes from a database: + +#include_code NoteGetterOptions /yarn-project/noir-libs/noir-aztec/src/note/note_getter_options.nr rust + +Developers can design instances of `NoteGetterOptions`, to determine how notes should be filtered and returned to the functions of their smart contracts. + +For example, the following function outputs an instance of `NoteGetterOptions`, which has been configured to 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 `CardNote` that has the following fields: + +#include_code state_vars-CardNote /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 `CardNote`, which is `owner`, and returns the cards whose `owner` field equals `account_address`. + +`.sort(0, SortOrder.DESC)` sorts the 0th field of `CardNote`, 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. + +> `Map` can map from `Field` or any native Noir type which is convertible to `Field`. + +### `::new` + +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 + +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. + +### `.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 71a407f228c..73bf120c164 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 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: + +#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 45557873862..a5d5008e78d 100644 --- a/docs/docs/dev_docs/contracts/syntax.md +++ b/docs/docs/dev_docs/contracts/syntax.md @@ -5,6 +5,7 @@ On top of [Noir's stdlib](https://noir-lang.org/standard_library/array_methods), we provide [Aztec.nr](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-libs) for writing contracts on Aztec. Aztec.nr contains abstractions which remove the need to understand the low-level Aztec protocol. Notably, it provides: + - Public and private [state variable types](./types.md) - Some pre-designed notes. - Functions for [emitting](./events.md) encrypted and unencrypted logs @@ -15,4 +16,4 @@ Aztec.nr contains abstractions which remove the need to understand the low-level To import Aztec.nr into your Aztec contract project, simply include it as a dependency. -#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 203ceefb7ac..983cade75af 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 00000000000..add81444e03 --- /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/account_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/account_contract_interface.nr new file mode 100644 index 00000000000..ca1b3b2d4a4 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/account_contract_interface.nr @@ -0,0 +1,12 @@ +struct AccountContractInterface { + address: Field, +} + +impl AccountContractInterface { + fn at(address: Field) -> Self { + AccountContractInterface { address } + } + + fn send_rewards(_self: Self, _rewards: u8) { + } +} \ 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 00000000000..3438b3db518 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/actions.nr @@ -0,0 +1,211 @@ +use dep::std::option::Option; +use dep::aztec::constants_gen::{MAX_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE}; +use dep::aztec::context::{ + PrivateContext, +}; +use dep::aztec::note::{ + note_getter_options::NoteGetterOptions, + note_viewer_options::NoteViewerOptions, +}; +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_note::{CardNote, CARD_NOTE_LEN}, + profile_note::{ProfileNote, PROFILE_NOTE_LEN}, + queen::{Queen, QUEEN_SERIALISED_LEN}, + rules_note::{RulesNote, RULES_NOTE_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-PublicStateReadWriteCustom +fn add_points_to_queen( + state_var: PublicState, + new_points: u8, +) { + let mut queen = state_var.read(); + queen.points += new_points; + state_var.write(queen); +} +// docs:end:state_vars-PublicStateReadWriteCustom + +// docs:start:state_vars-SingletonInit +fn init_legendary_card( + context: &mut PrivateContext, + state_var: Singleton, + card: &mut CardNote, +) { + 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 CardNote, +) { + 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, +) -> CardNote { + 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 RulesNote, +) { + 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: CardNote, +) -> 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 CardNote, + ) { + 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: CardNote, +) { + 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-SetView +unconstrained fn view_cards( + state_var: Set, + options: NoteViewerOptions, +) -> [Option; MAX_NOTES_PER_PAGE] { + state_var.view_notes(options) +} +// docs:end:state_vars-SetView + +unconstrained fn get_total_points(state_var: Set, account: Field, offset: u32) -> u8 { + let options = NoteViewerOptions::new().select(2, account).set_offset(offset); + let mut total_points = 0; + let notes = view_cards(state_var, options); + for i in 0..notes.len() { + if notes[i].is_some() { + total_points += notes[i].unwrap_unchecked().points; + } + } + if notes[notes.len() - 1].is_some() { + total_points += get_total_points(state_var, account, offset + notes.len() as u32); + } + total_points +} + +// docs:start:state_vars-SetContains +fn assert_contains_card( + context: &mut PrivateContext, + state_var: Set, + card: CardNote, +) { + 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 ProfileNote, +) { + 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, +) -> ProfileNote { + 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 00000000000..b29ed9b35a1 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr @@ -0,0 +1,178 @@ +mod account_contract_interface; +mod actions; +mod options; +mod storage; +mod types; + +contract DocsExample { + 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, + }; + + global REPLACE_QUEEN_FUNCTION_SELECTOR = 11111111; + global GET_POINTS_OF_COMMON_CARD_FUNCTION_SELECTOR = 11111111; + + #[aztec(private)] + fn constructor( + min_points: u8, + max_points: u8, + legendary_card_secret: Field, + ) { + let storage = Storage::init(); + + let mut game_rules = RulesNote::new(min_points, max_points); + actions::init_game_rules(&mut context, storage.game_rules, &mut game_rules); + + let mut legendary_card = CardNote::new(0, legendary_card_secret, 0); + actions::init_legendary_card(&mut context, storage.legendary_card, &mut legendary_card); + } + + // docs:start:storage-init + #[aztec(public)] + fn lock() { + // highlight-next-line:storage-init + let storage = Storage::init(); + storage.locked.write(true); + } + // docs:end:storage-init + + // docs:start:functions-OpenFunction + #[aztec(public)] + fn unlock() { + let storage = Storage::init(); + actions::unlock(storage.locked); + } + // docs:end:functions-OpenFunction + + #[aztec(public)] + fn replace_queen( + account: Field, + points: u8, + ) { + 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); + } + + // docs:start:state_vars-PublicStateWriteBeforeCall + #[aztec(public)] + fn replace_queen_unsafe() { + let storage = Storage::init(); + + let account = context.msg_sender(); + let points = actions::get_total_points(storage.cards, account, 0); + + let current_queen = storage.queen.read(); + assert(account != current_queen.account); + assert(points > current_queen.points); + + AccountContractInterface::at(account).send_rewards(current_queen.points); + + let new_queen = Queen { account, points }; + storage.queen.write(new_queen); + } + // docs:end:state_vars-PublicStateWriteBeforeCall + + // docs:start:functions-SecretFunction + #[aztec(private)] + fn add_common_cards(secrets: [Field; 4]) { + let storage = Storage::init(); + + for i in 0..secrets.len() as u8 { + let mut card = CardNote::new(0, secrets[i], 0); + actions::add_new_card(&mut context, storage.cards, &mut card); + } + } + // docs:end:functions-SecretFunction + + #[aztec(private)] + fn update_legendary_card( + new_points: u8, + new_secret: Field, + ) { + let storage = Storage::init(); + + let owner = inputs.call_context.msg_sender; + let mut updated_card = CardNote::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); + } + + #[aztec(private)] + fn become_queen() { + 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] + ); + } + + #[aztec(private)] + fn get_points_of_common_cards( + account: Field, + offset: u32, + ) { + let storage = Storage::init(); + + let mut total_points = 0; + let options = create_account_card_getter_options(account, offset); + let cards = actions::get_cards(&mut context, storage.cards, options); + for i in 0..cards.len() { + 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); + } + + // docs:start:state_vars-check_return_notes + #[aztec(private)] + fn discard_largest_card() { + let storage = Storage::init(); + + let account = context.msg_sender(); + let options = create_largest_account_card_getter_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); + } + // docs:end:state_vars-check_return_notes + + // docs:start:functions-UncontrainedFunction + unconstrained fn get_total_points(account: Field) -> u8 { + let storage = Storage::init(); + actions::get_total_points(storage.cards, account, 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 00000000000..7019f58016b --- /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_note::{CardNote, CARD_NOTE_LEN}; + +// docs:start:state_vars-NoteGetterOptionsSelectSortOffset +fn create_account_card_getter_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_exact_card_getter_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_account_cards_with_min_points_getter_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_largest_account_card_getter_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 00000000000..fc9ae590fd5 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/storage.nr @@ -0,0 +1,62 @@ +use dep::aztec::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::{ + BOOL_SERIALISED_LEN, + BoolSerialisationMethods, +}; +// docs:end:state_vars-PublicStateBoolImport + +use crate::types::{ + card_note::{CardNote, CARD_NOTE_LEN, CardNoteMethods}, + profile_note::{ProfileNote, PROFILE_NOTE_LEN, ProfileNoteMethods}, + queen::{Queen, QUEEN_SERIALISED_LEN, QueenSerialisationMethods}, + rules_note::{RulesNote, RULES_NOTE_LEN, RulesNoteMethods}, +}; + +// docs:start:storage-declaration +struct Storage { + locked: PublicState, + queen: PublicState, + game_rules: ImmutableSingleton, + legendary_card: Singleton, + cards: Set, + profiles: Map>, +} + +// 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() -> Self { + Storage { + // highlight-next-line:state_vars-PublicState + locked: PublicState::new(1, BoolSerialisationMethods), + // highlight-next-line:state_vars-PublicStateCustomStruct + queen: PublicState::new(2, QueenSerialisationMethods), + // highlight-next-line:state_vars-ImmutableSingleton + game_rules: ImmutableSingleton::new(3, RulesNoteMethods), + // highlight-next-line:state_vars-Singleton + legendary_card: Singleton::new(4, CardNoteMethods), + // highlight-next-line:state_vars-Set + cards: Set::new(5, CardNoteMethods), + // highlight-next-line:state_vars-MapSingleton + profiles: Map::new(6, |slot| Singleton::new(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 \ 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 00000000000..9e0784c92ca --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types.nr @@ -0,0 +1,4 @@ +mod card_note; +mod profile_note; +mod queen; +mod rules_note; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card_note.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card_note.nr new file mode 100644 index 00000000000..9d999c8aa7c --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/card_note.nr @@ -0,0 +1,97 @@ +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, +}; + +global CARD_NOTE_LEN: Field = 3; + +// docs:start:state_vars-CardNote +struct CardNote { + points: u8, + secret: Field, + owner: Field, + header: NoteHeader, +} +// docs:end:state_vars-CardNote + +impl CardNote { + fn new(points: u8, secret: Field, owner: Field) -> Self { + CardNote { + points, + secret, + owner, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; CARD_NOTE_LEN] { + [self.points as Field, self.secret, self.owner] + } + + fn deserialise(preimage: [Field; CARD_NOTE_LEN]) -> Self { + CardNote { + 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(CardNoteMethods, self); + let secret = get_secret_key(self.owner); + 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_NOTE_LEN]) -> CardNote { + CardNote::deserialise(preimage) +} + +fn serialise(note: CardNote) -> [Field; CARD_NOTE_LEN] { + note.serialise() +} + +fn compute_note_hash(note: CardNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: CardNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: CardNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut CardNote, header: NoteHeader) { + note.set_header(header) +} + +global CardNoteMethods = 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_note.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile_note.nr new file mode 100644 index 00000000000..9e8436e62c6 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/profile_note.nr @@ -0,0 +1,84 @@ +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, +}; + +global PROFILE_NOTE_LEN: Field = 2; + +struct ProfileNote { + avatar: Field, + xp: Field, + header: NoteHeader, +} + +impl ProfileNote { + fn new(avatar: Field, xp: Field) -> Self { + ProfileNote { + avatar, + xp, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; PROFILE_NOTE_LEN] { + [self.avatar, self.xp] + } + + fn deserialise(preimage: [Field; PROFILE_NOTE_LEN]) -> Self { + ProfileNote { + 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_NOTE_LEN]) -> ProfileNote { + ProfileNote::deserialise(preimage) +} + +fn serialise(note: ProfileNote) -> [Field; PROFILE_NOTE_LEN] { + note.serialise() +} + +fn compute_note_hash(note: ProfileNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: ProfileNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: ProfileNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut ProfileNote, header: NoteHeader) { + note.set_header(header) +} + +global ProfileNoteMethods = 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 00000000000..eb85a5d11f2 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/queen.nr @@ -0,0 +1,28 @@ +use dep::aztec::types::type_serialisation::TypeSerialisationInterface; + +// docs:start:state_vars-CustomStruct +struct Queen { + account: Field, + points: u8, +} +// docs:end:state_vars-CustomStruct + +// 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, +}; +// 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/rules_note.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules_note.nr new file mode 100644 index 00000000000..c204842484e --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/types/rules_note.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_NOTE_LEN: Field = 2; + +struct RulesNote { + min_points: u8, + max_points: u8, + header: NoteHeader, +} + +impl RulesNote { + fn new(min_points: u8, max_points: u8) -> Self { + RulesNote { + min_points, + max_points, + header: NoteHeader::empty(), + } + } + + fn serialise(self) -> [Field; RULES_NOTE_LEN] { + [self.min_points as Field, self.max_points as Field] + } + + fn deserialise(preimage: [Field; RULES_NOTE_LEN]) -> Self { + RulesNote { + 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_NOTE_LEN]) -> RulesNote { + RulesNote::deserialise(preimage) +} + +fn serialise(note: RulesNote) -> [Field; RULES_NOTE_LEN] { + note.serialise() +} + +fn compute_note_hash(note: RulesNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: RulesNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: RulesNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut RulesNote, header: NoteHeader) { + note.set_header(header) +} + +global RulesNoteMethods = 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 57ef1d2f441..bb14eea601f 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 @@ -13,9 +13,7 @@ contract PrivateToken { utils as note_utils, }; - // 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 52fcd691490..36e5fc8e9f4 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 9513325c9fa..ef39a851b2e 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 fd662fc3b47..84d171fd5ba 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 diff --git a/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr index dfe738d2c38..e1ccdde98f9 100644 --- a/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr @@ -5,7 +5,9 @@ mod u32_serialisation; /** * Before Noir supports traits, a way of specifying the serialisation and deserialisation methods for a type. */ +// docs:start:TypeSerialisationInterface struct TypeSerialisationInterface { deserialise: fn ([Field; N]) -> T, serialise: fn (T) -> [Field; N], -} \ No newline at end of file +} +// docs:end:TypeSerialisationInterface \ No newline at end of file