diff --git a/boxes/react/src/contracts/src/main.nr b/boxes/react/src/contracts/src/main.nr index 5389aeb170f..e57aac08ab1 100644 --- a/boxes/react/src/contracts/src/main.nr +++ b/boxes/react/src/contracts/src/main.nr @@ -1,20 +1,15 @@ contract BoxReact { use dep::aztec::{ - protocol_types::address::AztecAddress, - state_vars::{singleton::Singleton, map::Map}, - note::{ - utils as note_utils, - note_interface::NoteInterface, - note_header::NoteHeader, - }, + protocol_types::address::AztecAddress, state_vars::{PrivateMutable, Map}, + note::{utils as note_utils, note_interface::NoteInterface, note_header::NoteHeader} }; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; struct Storage { - numbers: Map>, + numbers: Map>, } - + #[aztec(private)] fn constructor(number: Field, owner: AztecAddress) { let numbers = storage.numbers; diff --git a/boxes/vanilla-js/src/contracts/src/main.nr b/boxes/vanilla-js/src/contracts/src/main.nr index 4a1f5daeedc..bb374393d5d 100644 --- a/boxes/vanilla-js/src/contracts/src/main.nr +++ b/boxes/vanilla-js/src/contracts/src/main.nr @@ -1,20 +1,15 @@ contract Vanilla { use dep::aztec::{ - protocol_types::address::AztecAddress, - state_vars::{singleton::Singleton, map::Map}, - note::{ - utils as note_utils, - note_interface::NoteInterface, - note_header::NoteHeader, - }, + protocol_types::address::AztecAddress, state_vars::{PrivateMutable, Map}, + note::{utils as note_utils, note_interface::NoteInterface, note_header::NoteHeader} }; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; struct Storage { - numbers: Map>, + numbers: Map>, } - + #[aztec(private)] fn constructor(number: Field, owner: AztecAddress) { let numbers = storage.numbers; diff --git a/docs/docs/developers/contracts/references/storage/main.md b/docs/docs/developers/contracts/references/storage/main.md index f8260d0313f..b59350ee35f 100644 --- a/docs/docs/developers/contracts/references/storage/main.md +++ b/docs/docs/developers/contracts/references/storage/main.md @@ -233,9 +233,9 @@ Reading through the storage variables: - `admin` a single Field value stored in public state. A `Field` is basically an unsigned integer with a maximum value determined by the underlying cryptographic curve. - `minters` is a mapping of Fields in public state. This will store whether an account is an approved minter on the contract. -- `balances` is a mapping of private balances. Private balances are stored in a `Set` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. +- `balances` is a mapping of private balances. Private balances are stored in a `PrivateSet` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. - `total_supply` is a Field value stored in public state and represents the total number of tokens minted. -- `pending_shields` is a `Set` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. +- `pending_shields` is a `PrivateSet` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. - `public_balances` is a mapping field elements in public state and represents the publicly viewable balances of accounts. You can read more about it [here](../storage/main.md). @@ -288,7 +288,7 @@ The function returns 1 to indicate successful execution. This public function allows an account approved in the public `minters` mapping to create new private tokens that can be claimed by anyone that has the pre-image to the `secret_hash`. -First, public storage is initialized. Then it checks that the `msg_sender` is an approved minter. Then a new `TransparentNote` is created with the specified `amount` and `secret_hash`. You can read the details of the `TransparentNote` in the `types.nr` file [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src/types.nr#L61). The `amount` is added to the existing public `total_supply` and the storage value is updated. Then the new `TransparentNote` is added to the `pending_shields` using the `insert_from_public` function, which is accessible on the `Set` type. Then it's ready to be claimed by anyone with the `secret_hash` pre-image using the `redeem_shield` function. It returns `1` to indicate successful execution. +First, public storage is initialized. Then it checks that the `msg_sender` is an approved minter. Then a new `TransparentNote` is created with the specified `amount` and `secret_hash`. You can read the details of the `TransparentNote` in the `types.nr` file [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src/types.nr#L61). The `amount` is added to the existing public `total_supply` and the storage value is updated. Then the new `TransparentNote` is added to the `pending_shields` using the `insert_from_public` function, which is accessible on the `PrivateSet` type. Then it's ready to be claimed by anyone with the `secret_hash` pre-image using the `redeem_shield` function. It returns `1` to indicate successful execution. #include_code mint_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/references/storage/private_state.md b/docs/docs/developers/contracts/references/storage/private_state.md index 61d3046a67c..ce9770ee2af 100644 --- a/docs/docs/developers/contracts/references/storage/private_state.md +++ b/docs/docs/developers/contracts/references/storage/private_state.md @@ -16,9 +16,9 @@ Aztec private state follows a [utxo](https://en.wikipedia.org/wiki/Unspent_trans 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) +- [PrivateMutable](#privatemutablenotetype) +- [PrivateImmutable](#privateimmutablenotetype) +- [PrivateSet](#privatesetnotetype) 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. @@ -42,51 +42,51 @@ A note should implement the following traits: 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. +A private state variable (of type `PrivateMutable`, `PrivateImmutable` or `PrivateSet`) may be declared in storage. Every note contains a header, which contains the contract address and storage slot of the state variable to which it is associated. A note is associated with a private state variable if the storage slot of the private state variable matches the storage slot contained in the note's header. The header provides information that helps the user interpret the note's data. -Management of the header is abstracted-away from developers who use the `ImmutableSingleton`, `Singleton` and `Set` types. +Management of the header is abstracted-away from developers who use the `PrivateImmutable`, `PrivateMutable` and `PrivateSet` types. A private state variable points to one or many notes (depending on the type). The note(s) are all valid private state if the note(s) haven't yet been nullified. -An `ImmutableSingleton` will point to _one_ note over the lifetime of the contract. This note is a struct of information that is persisted forever. +An `PrivateImmutable` will point to _one_ note over the lifetime of the contract. This note is a struct of information that is persisted forever. -A `Singleton` may point to _one_ note at a time. But since it's not "immutable", the note that it points to may be [replaced](#replace) by functions of the contract. 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. +A `PrivateMutable` may point to _one_ note at a time. But since it's not "immutable", the note that it points to may be [replaced](#replace) by functions of the contract. The current value of a `PrivateMutable` is interpreted as the one note which has not-yet been nullified. The act of replacing a PrivateMutable's note is how a `PrivateMutable` state may be modified by functions. -`Singleton` is a useful type when declaring a private state variable which may only ever be modified by those who are privy to the current value of that state. +`PrivateMutable` is a useful type when declaring a private state variable 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`. +A `PrivateSet` may point to _multiple_ notes at a time. The "current value" of a private state variable of type `PrivateSet` is some accumulation of all not-yet nullified notes which belong to the `PrivateSet`. :::note -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'). +The term "some accumulation" is intentionally vague. The interpretation of the "current value" of a `PrivateSet` must be expressed by the smart contract developer. A common use case for a `PrivateSet` 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. +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 `PrivateSet` state variable, is to [`insert`](#insert) new notes into the `PrivateSet`, 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!). +Interestingly, if a developer requires a private state to be modifiable by users who _aren't_ privy to the value of that state, a `PrivateSet` is a very useful type. The `insert` method allows new notes to be added to the `PrivateSet` 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` +## `PrivateMutable` -Singleton is a private state variable that is unique in a way. When a Singleton is initialized, 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. +PrivateMutable (formerly known as `Singleton`) is a private state variable that is unique in a way. When a PrivateMutable is initialized, 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. -Like for public state, we define the struct to have context and a storage slot. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/aztec/src/state_vars/singleton.nr). +Like for public state, we define the struct to have context and a storage slot. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr). -An example of singleton usage in the account contracts is keeping track of public keys. The `Singleton` is added to the `Storage` struct as follows: +An example of `PrivateMutable` usage in the account contracts is keeping track of public keys. The `PrivateMutable` is added to the `Storage` struct as follows: -#include_code storage-singleton-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code storage-private-mutable-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust ### `new` -As part of the initialization of the `Storage` struct, the `Singleton` is created as follows at the specified storage slot. +As part of the initialization of the `Storage` struct, the `PrivateMutable` is created as follows at the specified storage slot. -#include_code start_vars_singleton /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code start_vars_private_mutable /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust ### `initialize` -As mentioned, the Singleton is initialized to create the first note and value. +As mentioned, the PrivateMutable is initialized to create the first note and value. -When this function is called, a nullifier of the storage slot is created, preventing this Singleton from being initialized again. +When this function is called, a nullifier of the storage slot is created, preventing this PrivateMutable from being initialized again. :::danger Privacy-Leak Beware that because this nullifier is created only from the storage slot without randomness it leaks privacy. This means that it is possible for an external observer to determine when the note is nullified. @@ -94,7 +94,7 @@ Beware that because this nullifier is created only from the storage slot without For example, if the storage slot depends on the an address then it is possible to link the nullifier to the address. If the singleton is part of a `map` with an `AztecAddress` as the key then the nullifier will be linked to the address. ::: -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 `initialize` method (or `insert`, in the case of a `Set`) must be called. +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 `PrivateMutable`, `PrivateImmutable` or `PrivateSet`) does not have a default initial value. The `initialize` method (or `insert`, in the case of a `PrivateSet`) must be called. :::info Extend on what happens if you try to use non-initialized state. @@ -102,29 +102,29 @@ Extend on what happens if you try to use non-initialized state. ### `is_initialized` -An unconstrained method to check whether the Singleton has been initialized or not. It takes an optional owner and returns a boolean. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/singleton.nr). +An unconstrained method to check whether the PrivateMutable has been initialized or not. It takes an optional owner and returns a boolean. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr). -#include_code singleton_is_initialized /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code private_mutable_is_initialized /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust ### `replace` -To update the value of a `Singleton`, we can use the `replace` method. The method takes a new note as input, and replaces the current note with the new one. It emits a nullifier for the old value, and inserts the new note into the data tree. +To update the value of a `PrivateMutable`, we can use the `replace` method. The method takes a new note as input, and replaces the current note with the new one. It emits a nullifier for the old value, and inserts the new note into the data tree. An example of this is seen in a example card game, where we create a new note (a `CardNote`) containing some new data, and replace the current note with it: -#include_code state_vars-SingletonReplace /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code state_vars-PrivateMutableReplace /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust -If two people are trying to modify the Singleton at the same time, only one will succeed as we don't allow duplicate nullifiers! Developers should put in place appropriate access controls to avoid race conditions (unless a race is intended!). +If two people are trying to modify the PrivateMutable at the same time, only one will succeed as we don't allow duplicate nullifiers! 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, essentially reading the value. +This function allows us to get the note of a PrivateMutable, essentially reading the value. -#include_code state_vars-SingletonGet /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code state_vars-PrivateMutableGet /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust #### Nullifying Note reads -To ensure that a user's private execution always uses the latest value of a Singleton, the `get_note` function will nullify the note that it is reading. This means that if two people are trying to use this function with the same note, only one will succeed (no duplicate nullifiers allowed). +To ensure that a user's private execution always uses the latest value of a PrivateMutable, the `get_note` function will nullify the note that it is reading. This means that if two people are trying to use this function with the same note, only one will succeed (no duplicate nullifiers allowed). This also makes read operations indistinguishable from write operations and allows the sequencer to verifying correct execution without learning anything about the value of the note. @@ -132,19 +132,19 @@ This also makes read operations indistinguishable from write operations and allo Functionally similar to [`get_note`](#get_note), but executed in unconstrained functions and can be used by the wallet to fetch notes for use by front-ends etc. -## `ImmutableSingleton` +## `PrivateImmutable` -`ImmutableSingleton` represents a unique private state variable that, as the name suggests, is immutable. Once initialized, its value cannot be altered. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/immutable_singleton.nr). +`PrivateImmutable` (formerly known as `ImmutableSingleton`) represents a unique private state variable that, as the name suggests, is immutable. Once initialized, its value cannot be altered. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr). ### `new` -As part of the initialization of the `Storage` struct, the `Singleton` is created as follows, here at storage slot 1. +As part of the initialization of the `Storage` struct, the `PrivateMutable` is created as follows, here at storage slot 1. -#include_code storage-immutable-singleton-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code storage-private-immutable-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust ### `initialize` -When this function is invoked, it creates a nullifier for the storage slot, ensuring that the ImmutableSingleton cannot be initialized again. +When this function is invoked, it creates a nullifier for the storage slot, ensuring that the PrivateImmutable cannot be initialized again. :::danger Privacy-Leak Beware that because this nullifier is created only from the storage slot without randomness it leaks privacy. This means that it is possible for an external observer to determine when the note is nullified. @@ -152,35 +152,35 @@ Beware that because this nullifier is created only from the storage slot without For example, if the storage slot depends on the an address then it is possible to link the nullifier to the address. If the singleton is part of a `map` with an `AztecAddress` as the key then the nullifier will be linked to the address. ::: -Set the value of an ImmutableSingleton by calling the `initialize` method: +Set the value of an PrivateImmutable by calling the `initialize` method: -#include_code initialize-immutable-singleton /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code initialize-private-mutable /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust -Once initialized, an ImmutableSingleton's value remains unchangeable. This method can only be called once. +Once initialized, an PrivateImmutable's value remains unchangeable. This method can only be called once. ### `is_initialized` -An unconstrained method to check if the ImmutableSingleton has been initialized. Takes an optional owner and returns a boolean. You can find the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/immutable_singleton.nr). +An unconstrained method to check if the PrivateImmutable has been initialized. Takes an optional owner and returns a boolean. You can find the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr). ### `get_note` -Similar to the `Singleton`, we can use the `get_note` method to read the value of an ImmutableSingleton. +Similar to the `PrivateMutable`, we can use the `get_note` method to read the value of an PrivateImmutable. -Use this method to retrieve the value of an initialized ImmutableSingleton. +Use this method to retrieve the value of an initialized PrivateImmutable. -#include_code get_note-immutable-singleton /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code get_note-private-immutable /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust -Unlike a `Singleton`, the `get_note` function for an ImmutableSingleton doesn't nullify the current note in the background. This means that multiple accounts can concurrently call this function to read the value. +Unlike a `PrivateMutable`, the `get_note` function for an PrivateImmutable doesn't nullify 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 initialized. +This function will throw if the `PrivateImmutable` hasn't been initialized. ### `view_note` Functionally similar to `get_note`, but executed unconstrained and can be used by the wallet to fetch notes for use by front-ends etc. -## `Set` +## `PrivateSet` -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 up to the developer. The set is a collection of notes inserted into the data-tree, but notes are never removed from the tree itself, they are only nullified. +`PrivateSet` is used for managing a collection of notes. All notes in a `PrivateSet` are of the same `NoteType`. But whether these notes all belong to one entity, or are accessible and editable by different entities, is up to the developer. The set is a collection of notes inserted into the data-tree, but notes are never removed from the tree itself, they are only nullified. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/set.nr). @@ -198,7 +198,7 @@ We can initialize the set as follows: ### `insert` -Allows us to modify the storage by inserting a note into the set. +Allows us to modify the storage by inserting a note into the `PrivateSet`. A hash of the note will be generated, and inserted into the note hash tree, allowing us to later use in contract interactions. Recall that the content of the note should be shared with the owner to allow them to use it, as mentioned this can be done via an [encrypted log](../../writing_contracts/events/emit_event.md#encrypted-events), or offchain via web2, or completely offline. @@ -214,7 +214,7 @@ The usage is similar to using the `insert` method with the difference that this ### `remove` -Will remove a note from the set if it previously has been read from storage, e.g. you have fetched it through a `get_notes` call. This is useful when you want to remove a note that you have previously read from storage and do not have to read it again. +Will remove a note from the `PrivateSet` if it previously has been read from storage, e.g. you have fetched it through a `get_notes` call. This is useful when you want to remove a note that you have previously read from storage and do not have to read it again. Nullifiers are emitted when reading values to make sure that they are up to date. diff --git a/docs/docs/developers/contracts/references/storage/public_state.md b/docs/docs/developers/contracts/references/storage/public_state.md index d96866b4fd8..4344c0b0d10 100644 --- a/docs/docs/developers/contracts/references/storage/public_state.md +++ b/docs/docs/developers/contracts/references/storage/public_state.md @@ -8,14 +8,14 @@ For a higher level overview of the state model in Aztec, see the [state model](. ## Overview -The `PublicState` struct is generic over the variable type `T`. The type _must_ implement Serialize and Deserialize traits, as specified here: +The `PublicMutable` (formerly known as `PublicState`) struct is generic over the variable type `T`. The type _must_ implement Serialize and Deserialize traits, as specified here: #include_code serialize /noir-projects/noir-protocol-circuits/src/crates/types/src/traits.nr rust #include_code deserialize /noir-projects/noir-protocol-circuits/src/crates/types/src/traits.nr rust The struct contains a `storage_slot` which, similar to Ethereum, is used to figure out _where_ in storage the variable is located. Notice that while we don't have the exact same [state model](../../../../learn/concepts/hybrid_state/main.md) as EVM chains it will look similar from the contract developers point of view. -You can find the details of `PublicState` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr). +You can find the details of `PublicMutable` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr). :::info An example using a larger struct can be found in the [lending example](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts/lending_contract)'s use of an [`Asset`](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr). @@ -23,7 +23,7 @@ An example using a larger struct can be found in the [lending example](https://g ### `new` -When declaring the storage for `T` as a persistent public storage variable, we use the `PublicState::new()` constructor. As seen below, this takes the `storage_slot` and the `serialization_methods` as arguments along with the [`Context`](../../writing_contracts/functions/context.md), which in this case is used to share interface with other structures. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr). +When declaring the storage for `T` as a persistent public storage variable, we use the `PublicMutable::new()` constructor. As seen below, this takes the `storage_slot` and the `serialization_methods` as arguments along with the [`Context`](../../writing_contracts/functions/context.md), which in this case is used to share interface with other structures. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr). #### Single value example @@ -61,7 +61,7 @@ mapping(address => bool) internal minters; ### `read` -On the `PublicState` structs we have a `read` method to read the value at the location in storage. +On the `PublicMutable` structs we have a `read` method to read the value at the location in storage. #### Reading from our `admin` example @@ -77,7 +77,7 @@ As we saw in the Map earlier, a very similar operation can be done to perform a ### `write` -We have a `write` method on the `PublicState` struct that takes the value to write as an input and saves this in storage. It uses the serialization method to serialize the value which inserts (possibly multiple) values into storage. +We have a `write` method on the `PublicMutable` struct that takes the value to write as an input and saves this in storage. It uses the serialization method to serialize the value which inserts (possibly multiple) values into storage. #### Writing to our `admin` example @@ -89,25 +89,29 @@ We have a `write` method on the `PublicState` struct that takes the value to wri --- -## Stable Public State +## Shared Immutable -`StablePublicState` is a special type of `PublicState` that can be read from both public and private! +`SharedImmutable` (formerly known as `StablePublicState`) is a special type that can be read from both public and private! Since private execution is based on historical data, the user can pick ANY of its prior values to read from. This is why it `MUST` not be updated after the contract is deployed. The variable should be initialized at the constructor and then never changed. -This makes the stable public variables useful for stuff that you would usually have in `immutable` values in solidity. For example this can be the name of a token or its number of decimals. +This makes the immutable public variables useful for stuff that you would usually have in `immutable` values in solidity. For example this can be the name of a token or its number of decimals. -Just like the `PublicState` it is generic over the variable type `T`. The type `MUST` implement Serialize and Deserialize traits. +Just like the `PublicMutable` it is generic over the variable type `T`. The type `MUST` implement Serialize and Deserialize traits. -You can find the details of `StablePublicState` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/stable_public_state.nr). +You can find the details of `SharedImmutable` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr). + +:::info +The word `Shared` in Aztec protocol means read/write from public, read only from private. +::: ### `new` -Is done exactly like the `PublicState` struct, but with the `StablePublicState` struct. +Is done exactly like the `PublicMutable` struct, but with the `SharedImmutable` struct. -#include_code storage-stable-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code storage-shared-immutable-declaration /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust -#include_code storage-stable-init /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust +#include_code storage-shared-immutable /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust ### `initialize` @@ -121,11 +125,11 @@ Currently this is not constrained as we are in the middle of changing deployment ### `read_public` -Reading the value is like `PublicState`, simply with `read_public` instead of `read`. +Reading the value is like `PublicMutable`, simply with `read_public` instead of `read`. #include_code read_decimals_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust ### `read_private` -Reading the value is like `PublicState`, simply with `read_private` instead of `read`. This part can only be executed in private. +Reading the value is like `PublicMutable`, simply with `read_private` instead of `read`. This part can only be executed in private. #include_code read_decimals_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/resources/common_patterns/main.md b/docs/docs/developers/contracts/resources/common_patterns/main.md index 51b733e2ef0..c6c31296a0e 100644 --- a/docs/docs/developers/contracts/resources/common_patterns/main.md +++ b/docs/docs/developers/contracts/resources/common_patterns/main.md @@ -54,7 +54,7 @@ You can't read public storage in private domain. But nevertheless reading public ```rust struct Storage { - token: PublicState, + token: PublicMutable, } contract Bridge { diff --git a/docs/docs/developers/sandbox/references/cheat_codes.md b/docs/docs/developers/sandbox/references/cheat_codes.md index d9c04dddfd9..2f206adcae0 100644 --- a/docs/docs/developers/sandbox/references/cheat_codes.md +++ b/docs/docs/developers/sandbox/references/cheat_codes.md @@ -462,13 +462,13 @@ The baseSlot is specified in the Aztec.nr contract. ```rust struct Storage { - balances: Map>, + balances: Map>, } impl Storage { fn init() -> Self { Storage { - balances: Map::new(1, |slot| PublicState::new(slot)), + balances: Map::new(1, |slot| PublicMutable::new(slot)), } } } @@ -500,13 +500,13 @@ Note: One Field element occupies a storage slot. Hence, structs with multiple fi ```rust struct Storage { - balances: Map>, + balances: Map>, } impl Storage { fn init(context: Context) -> Self { Storage { - balances: Map::new(context, 1, |context, slot| PublicState::new(context, slot)), + balances: Map::new(context, 1, |context, slot| PublicMutable::new(context, slot)), } } } diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index 46766c3da23..cf69867fe26 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -73,7 +73,7 @@ We are using various utils within the Aztec library: - `context` - exposes things such as the contract address, msg_sender, etc - `context.request_nullifier_secret_key` - get your secret key to help us create a randomized nullifier - `FunctionSelector::from_signature` - compute a function selector from signature so we can call functions from other functions -- `state_vars::{ map::Map, public_state::PublicState, }` - we will use a Map to store the votes (key = voteId, value = number of votes), and PublicState to hold our public values that we mentioned earlier +- `state_vars::{Map, PublicMutable}` - we will use a Map to store the votes (key = voteId, value = number of votes), and PublicMutable to hold our public values that we mentioned earlier - `types::type_serialization::{..}` - various serialization methods for defining how to use these types - `types::address::{AztecAddress},` - our admin will be held as an address - `constants::EMPTY_NULLIFIED_COMMITMENT,` - this will come in useful when creating our nullifier diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index 7a0960f0f2d..1d6f4098b3d 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -233,9 +233,9 @@ Reading through the storage variables: - `admin` a single Field value stored in public state. A `Field` is basically an unsigned integer with a maximum value determined by the underlying cryptographic curve. - `minters` is a mapping of Fields in public state. This will store whether an account is an approved minter on the contract. -- `balances` is a mapping of private balances. Private balances are stored in a `Set` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. +- `balances` is a mapping of private balances. Private balances are stored in a `PrivateSet` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. - `total_supply` is a Field value stored in public state and represents the total number of tokens minted. -- `pending_shields` is a `Set` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. +- `pending_shields` is a `PrivateSet` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. - `public_balances` is a mapping field elements in public state and represents the publicly viewable balances of accounts. You can read more about it [here](../contracts/writing_contracts/storage/main.md). @@ -288,7 +288,7 @@ The function returns 1 to indicate successful execution. This public function allows an account approved in the public `minters` mapping to create new private tokens that can be claimed by anyone that has the pre-image to the `secret_hash`. -First, public storage is initialized. Then it checks that the `msg_sender` is an approved minter. Then a new `TransparentNote` is created with the specified `amount` and `secret_hash`. You can read the details of the `TransparentNote` in the `types.nr` file [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src/types.nr#L61). The `amount` is added to the existing public `total_supply` and the storage value is updated. Then the new `TransparentNote` is added to the `pending_shields` using the `insert_from_public` function, which is accessible on the `Set` type. Then it's ready to be claimed by anyone with the `secret_hash` pre-image using the `redeem_shield` function. It returns `1` to indicate successful execution. +First, public storage is initialized. Then it checks that the `msg_sender` is an approved minter. Then a new `TransparentNote` is created with the specified `amount` and `secret_hash`. You can read the details of the `TransparentNote` in the `types.nr` file [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src/types.nr#L61). The `amount` is added to the existing public `total_supply` and the storage value is updated. Then the new `TransparentNote` is added to the `pending_shields` using the `insert_from_public` function, which is accessible on the `PrivateSet` type. Then it's ready to be claimed by anyone with the `secret_hash` pre-image using the `redeem_shield` function. It returns `1` to indicate successful execution. #include_code mint_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/docs/docs/learn/concepts/storage/storage_slots.md b/docs/docs/learn/concepts/storage/storage_slots.md index 9afb68ae05d..a18afb9577b 100644 --- a/docs/docs/learn/concepts/storage/storage_slots.md +++ b/docs/docs/learn/concepts/storage/storage_slots.md @@ -44,7 +44,7 @@ note_hash = H(logical_storage_slot, note_content_hash); This siloing (there will be more) is done in the application circuit, since it is not necessary for security of the network (but only the application). :::info -The private variable wrappers `Set` and `Singleton` in Aztec.nr include the `logical_storage_slot` in the commitments they compute, to make it easier for developers to write contracts without having to think about how to correctly handle storage slots. +The private variable wrappers `PrivateSet` and `PrivateMutable` in Aztec.nr include the `logical_storage_slot` in the commitments they compute, to make it easier for developers to write contracts without having to think about how to correctly handle storage slots. ::: When reading the values for these notes, the application circuit can then constrain the values to only read notes with a specific logical storage slot. diff --git a/docs/docs/learn/concepts/storage/trees/main.md b/docs/docs/learn/concepts/storage/trees/main.md index 672e3b0aac0..826aa7364a2 100644 --- a/docs/docs/learn/concepts/storage/trees/main.md +++ b/docs/docs/learn/concepts/storage/trees/main.md @@ -142,9 +142,9 @@ A note cannot actually be "deleted" from the Note Hash Tree because it is an app > Note: this nullifier derivation example is an oversimplification for the purposes of illustration. -#### Initializing Singleton Notes +#### Initializing Notes wrapped by PrivateMutable -'Singleton Note' is a term we've been using to mean: "A single Note which contains the whole of a private state's current value, and must be deleted and replaced with another single Note, if one ever wishes to edit that state". It's in contrast to a Note which only contains a small fragment of a private state's current value. A token balance represented by multiple notes is an example of private state that uses many notes. +Notes wrapped 'PrivateMutable' have the following meaning: "A single Note which contains the whole of a private state's current value, and must be deleted and replaced with another single Note, if one ever wishes to edit that state". It's in contrast to a Note which only contains a small fragment of a private state's current value. A token balance represented by multiple notes is an example of private state that uses many notes. Such notes require an 'Initialization Nullifier'; a nullifier which, when emitted, signals the initialization of this state variable (i.e. the very first time the state variable has been written to). diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 4c1d9253bb7..0a95e994b1d 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -14,6 +14,21 @@ Historically developers have been required to include a `compute_note_hash_and_n It is possible to provide a user-defined implementation, in which case auto-generation will be skipped (though there are no known use cases for this). +### Updated naming of state variable wrappers +We have decided to change the naming of our state variable wrappers because the naming was not clear. +The changes are as follows: +1. `Singleton` -> `PrivateMutable` +2. `ImmutableSingleton` -> `PrivateImmutable` +3. `StablePublicState` -> `SharedImmutable` +5. `PublicState` -> `PublicMutable` + +This is the meaning of "private", "public" and "shared": +Private: read (R) and write (W) from private, not accessible from public +Public: not accessible from private, R/W from public +Shared: R from private, R/W from public + +Note: `SlowUpdates` will be renamed to `SharedMutable` once the implementation is ready. + ## 0.24.0 ### Introduce Note Type IDs @@ -194,27 +209,27 @@ struct Storage { legendary_card: Singleton, profiles: Map>, test: Set, - imm_singleton: ImmutableSingleton, + imm_singleton: PrivateImmutable, } impl Storage { fn init(context: Context) -> Self { Storage { - leader: PublicState::new( + leader: PublicMutable::new( context, 1, LeaderSerializationMethods, ), - legendary_card: Singleton::new(context, 2, CardNoteMethods), + legendary_card: PrivateMutable::new(context, 2, CardNoteMethods), profiles: Map::new( context, 3, |context, slot| { - Singleton::new(context, slot, CardNoteMethods) + PrivateMutable::new(context, slot, CardNoteMethods) }, ), test: Set::new(context, 4, CardNoteMethods), - imm_singleton: ImmutableSingleton::new(context, 4, CardNoteMethods), + imm_singleton: PrivateImmutable::new(context, 4, CardNoteMethods), } } } @@ -224,11 +239,11 @@ Now: ```rust struct Storage { - leader: PublicState, + leader: PublicMutable, legendary_card: Singleton, profiles: Map>, test: Set, - imm_singleton: ImmutableSingleton, + imm_singleton: PrivateImmutable, } ``` @@ -462,20 +477,20 @@ It is still possible to manually implement the storage initialization (for custo impl Storage { fn init(context: Context) -> Self { Storage { - leader: PublicState::new( + leader: PublicMutable::new( context, 1 ), - legendary_card: Singleton::new(context, 2), + legendary_card: PrivateMutable::new(context, 2), profiles: Map::new( context, 3, |context, slot| { - Singleton::new(context, slot) + PrivateMutable::new(context, slot) }, ), test: Set::new(context, 4), - imm_singleton: ImmutableSingleton::new(context, 4), + imm_singleton: PrivateImmutable::new(context, 4), } } } @@ -554,7 +569,7 @@ Before: ```rust struct Storage { - balances: Map> + balances: Map> } let user_balance = balances.at(owner.to_field()) diff --git a/l1-contracts/slither_output.md b/l1-contracts/slither_output.md index b9669bc5038..7de568caa47 100644 --- a/l1-contracts/slither_output.md +++ b/l1-contracts/slither_output.md @@ -353,15 +353,15 @@ src/core/messagebridge/Inbox.sol#L148-L153 Impact: Informational Confidence: Medium - [ ] ID-41 -Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L123) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L116) +Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L122) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L115) -src/core/libraries/ConstantsGen.sol#L123 +src/core/libraries/ConstantsGen.sol#L122 - [ ] ID-42 -Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L103) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L104) +Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L102) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L103) -src/core/libraries/ConstantsGen.sol#L103 +src/core/libraries/ConstantsGen.sol#L102 - [ ] ID-43 diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 6f1202c6c09..1595e0cea21 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -69,7 +69,6 @@ library Constants { uint256 internal constant L1_TO_L2_MSG_SUBTREE_HEIGHT = 4; uint256 internal constant L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH = 12; uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4; - uint256 internal constant MAPPING_SLOT_PEDERSEN_SEPARATOR = 4; uint256 internal constant NUM_FIELDS_PER_SHA256 = 2; uint256 internal constant ARGS_HASH_CHUNK_LENGTH = 32; uint256 internal constant ARGS_HASH_CHUNK_COUNT = 32; diff --git a/noir-projects/aztec-nr/authwit/src/account.nr b/noir-projects/aztec-nr/authwit/src/account.nr index 5d82902efc4..20816c6ae61 100644 --- a/noir-projects/aztec-nr/authwit/src/account.nr +++ b/noir-projects/aztec-nr/authwit/src/account.nr @@ -1,5 +1,5 @@ use dep::aztec::context::{PrivateContext, PublicContext, Context}; -use dep::aztec::state_vars::{map::Map, public_state::PublicState}; +use dep::aztec::state_vars::{Map, PublicMutable}; use crate::entrypoint::{app::AppPayload, fee::FeePayload}; use crate::auth::IS_VALID_SELECTOR; @@ -7,7 +7,7 @@ use crate::auth::IS_VALID_SELECTOR; struct AccountActions { context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool, - approved_action: Map>, + approved_action: Map>, } impl AccountActions { @@ -23,7 +23,7 @@ impl AccountActions { context, approved_action_storage_slot, |context, slot| { - PublicState::new(context, slot) + PublicMutable::new(context, slot) } ) } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index f504a8b392e..3f4185d047c 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -95,6 +95,11 @@ impl PrivateContext { } } + pub fn is_deployment(self) -> bool { + // TODO(#4738): Implement this + false + } + pub fn msg_sender(self) -> AztecAddress { self.inputs.call_context.msg_sender } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 9b82f578464..c75f79d902d 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -70,6 +70,11 @@ impl PublicContext { } } + pub fn is_deployment(self) -> bool { + // TODO(#4738): Implement this + false + } + pub fn msg_sender(self) -> AztecAddress { self.inputs.call_context.msg_sender } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars.nr b/noir-projects/aztec-nr/aztec/src/state_vars.nr index 177844f75c1..4201723eb07 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars.nr @@ -1,7 +1,15 @@ -mod immutable_singleton; mod map; -mod public_state; -mod set; -mod singleton; -mod stable_public_state; +mod private_immutable; +mod private_mutable; +mod public_mutable; +mod private_set; +mod shared_immutable; mod storage; + +use crate::state_vars::map::Map; +use crate::state_vars::private_immutable::PrivateImmutable; +use crate::state_vars::private_mutable::PrivateMutable; +use crate::state_vars::public_mutable::PublicMutable; +use crate::state_vars::private_set::PrivateSet; +use crate::state_vars::shared_immutable::SharedImmutable; +use crate::state_vars::storage::Storage; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/immutable_singleton.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr similarity index 92% rename from noir-projects/aztec-nr/aztec/src/state_vars/immutable_singleton.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index fed2d66a589..0803486551c 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/immutable_singleton.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -10,15 +10,15 @@ use crate::oracle::notes::check_nullifier_exists; use crate::state_vars::storage::Storage; // docs:start:struct -struct ImmutableSingleton { +struct PrivateImmutable { context: Option<&mut PrivateContext>, storage_slot: Field, } // docs:end:struct -impl Storage for ImmutableSingleton {} +impl Storage for PrivateImmutable {} -impl ImmutableSingleton { +impl PrivateImmutable { // docs:start:new pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); @@ -30,7 +30,7 @@ impl ImmutableSingleton { // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address. // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable. // Under such circumstances, such application developers might wish to _not_ use this state variable type. - // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. + // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. // e.g. the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address. pub fn compute_initialization_nullifier(self) -> Field { pedersen_hash( diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/singleton.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr similarity index 94% rename from noir-projects/aztec-nr/aztec/src/state_vars/singleton.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 137a0767d4e..14dd9609c05 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/singleton.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -11,15 +11,15 @@ use crate::oracle::{nullifier_key::get_nullifier_secret_key, notes::check_nullif use crate::state_vars::storage::Storage; // docs:start:struct -struct Singleton { +struct PrivateMutable { context: Option<&mut PrivateContext>, storage_slot: Field } // docs:end:struct -impl Storage for Singleton {} +impl Storage for PrivateMutable {} -impl Singleton { +impl PrivateMutable { // docs:start:new pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); @@ -31,7 +31,7 @@ impl Singleton { // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address. // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable. // Under such circumstances, such application developers might wish to _not_ use this state variable type. - // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. e.g. + // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. e.g. // the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address. // Note: subsequent nullification of this state variable, via the `replace` method will not be leaky, if the `compute_nullifier()` method of the underlying note is designed to ensure privacy. // For example, if the `compute_nullifier()` method injects the secret key of a note owner into the computed nullifier's preimage. diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr similarity index 89% rename from noir-projects/aztec-nr/aztec/src/state_vars/set.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 2a56fb1f8da..03d676f291f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -13,19 +13,19 @@ use crate::note::{ use crate::state_vars::storage::Storage; // docs:start:struct -struct Set { +struct PrivateSet { context: Context, storage_slot: Field, } // docs:end:struct -impl Storage for Set {} +impl Storage for PrivateSet {} -impl Set { +impl PrivateSet { // docs:start:new pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - Set { context, storage_slot } + PrivateSet { context, storage_slot } } // docs:end:new // docs:start:insert @@ -48,14 +48,14 @@ impl Set { // DEPRECATED fn assert_contains_and_remove(_self: Self, _note: &mut Note, _nonce: Field) { assert( - false, "`assert_contains_and_remove` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use Set.get_notes() and Set.remove() in your contract to verify and remove a note." + false, "`assert_contains_and_remove` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use PrivateSet.get_notes() and PrivateSet.remove() in your contract to verify and remove a note." ); } // DEPRECATED fn assert_contains_and_remove_publicly_created(_self: Self, _note: &mut Note) { assert( - false, "`assert_contains_and_remove_publicly_created` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use Set.get_notes() and Set.remove() in your contract to verify and remove a note." + false, "`assert_contains_and_remove_publicly_created` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use PrivateSet.get_notes() and PrivateSet.remove() in your contract to verify and remove a note." ); } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr similarity index 58% rename from noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr index 883a2f7a3df..5c474846357 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr @@ -5,40 +5,40 @@ use dep::std::option::Option; use dep::protocol_types::traits::{Deserialize, Serialize}; use crate::state_vars::storage::Storage; -// docs:start:public_state_struct -struct PublicState { +// docs:start:public_mutable_struct +struct PublicMutable { context: Context, storage_slot: Field, } -// docs:end:public_state_struct +// docs:end:public_mutable_struct -impl Storage for PublicState {} +impl Storage for PublicMutable {} -impl PublicState { - // docs:start:public_state_struct_new +impl PublicMutable { + // docs:start:public_mutable_struct_new pub fn new( // Note: Passing the contexts to new(...) just to have an interface compatible with a Map. context: Context, storage_slot: Field ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - PublicState { context, storage_slot } + PublicMutable { context, storage_slot } } - // docs:end:public_state_struct_new + // docs:end:public_mutable_struct_new - // docs:start:public_state_struct_read + // docs:start:public_mutable_struct_read pub fn read(self) -> T where T: Deserialize { - assert(self.context.private.is_none(), "Public state writes only supported in public functions"); + assert(self.context.private.is_none(), "PublicMutable reads only supported in public functions"); let fields = storage_read(self.storage_slot); T::deserialize(fields) } - // docs:end:public_state_struct_read + // docs:end:public_mutable_struct_read - // docs:start:public_state_struct_write + // docs:start:public_mutable_struct_write pub fn write(self, value: T) where T: Serialize { - assert(self.context.private.is_none(), "Public state writes only supported in public functions"); + assert(self.context.private.is_none(), "PublicMutable writes only supported in public functions"); let fields = T::serialize(value); storage_write(self.storage_slot, fields); } - // docs:end:public_state_struct_write + // docs:end:public_mutable_struct_write } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/stable_public_state.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr similarity index 56% rename from noir-projects/aztec-nr/aztec/src/state_vars/stable_public_state.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr index 9612fb30a5d..8720a8f58c5 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/stable_public_state.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr @@ -1,18 +1,17 @@ -use crate::context::{Context}; -use crate::oracle::{storage::{storage_read, storage_write}}; -use crate::history::public_value_inclusion::prove_public_value_inclusion; -use dep::std::option::Option; -use dep::protocol_types::traits::{Deserialize, Serialize}; -use crate::state_vars::storage::Storage; - -struct StablePublicState{ +use crate::{ + context::Context, history::public_value_inclusion::prove_public_value_inclusion, + oracle::{storage::{storage_read, storage_write}}, state_vars::storage::Storage +}; +use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}}; + +struct SharedImmutable{ context: Context, storage_slot: Field, } -impl Storage for StablePublicState {} +impl Storage for SharedImmutable {} -impl StablePublicState { +impl SharedImmutable { pub fn new( // Note: Passing the contexts to new(...) just to have an interface compatible with a Map. context: Context, @@ -24,12 +23,24 @@ impl StablePublicState { // Intended to be only called once. pub fn initialize(self, value: T) where T: Serialize { - assert(self.context.private.is_none(), "Public state wrties only supported in public functions"); - // TODO: Must throw if the storage slot is not empty -> cannot allow overwriting - // This is currently impractical, as public functions are never marked `is_contract_deployment` - // in the `call_context`, only private functions will have this flag set. - let fields = T::serialize(value); - storage_write(self.storage_slot, fields); + assert( + self.context.private.is_none(), "SharedImmutable can only be initialized from public functions" + ); + // TODO(#4738): Uncomment the following assert + // assert( + // self.context.public.unwrap_unchecked().is_deployment(), "SharedImmutable can only be initialized during contract deployment" + // ); + + // We check that the struct is not yet initialized by checking if the initialization slot is 0 + let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; + let fields_read: [Field; 1] = storage_read(initialization_slot); + assert(fields_read[0] == 0, "SharedImmutable already initialized"); + + // We populate the initialization slot with a non-zero value to indicate that the struct is initialized + storage_write(initialization_slot, [0xdead]); + + let fields_write = T::serialize(value); + storage_write(self.storage_slot, fields_write); } pub fn read_public(self) -> T where T: Deserialize { diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr index 5f28b55f9f7..e742ab7e036 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr @@ -1,4 +1,3 @@ -use crate::context::{Context}; use dep::protocol_types::traits::{Deserialize, Serialize}; trait Storage where T: Serialize + Deserialize { diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index 06664d9ccb7..e9f5c34dcd7 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -2,7 +2,7 @@ use dep::aztec::{ protocol_types::address::AztecAddress, context::Context, note::note_getter_options::NoteGetterOptions, - state_vars::set::Set, + state_vars::PrivateSet, }; use dep::value_note::{ filter::filter_notes_min_sum, @@ -11,7 +11,7 @@ use dep::value_note::{ struct EasyPrivateUint { context: Context, - set: Set, + set: PrivateSet, storage_slot: Field, } @@ -22,7 +22,7 @@ impl EasyPrivateUint { storage_slot: Field, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - let set = Set { + let set = PrivateSet { context, storage_slot }; diff --git a/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr b/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr index aee68bcb36e..bbfa414e523 100644 --- a/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr +++ b/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr @@ -17,6 +17,7 @@ fn compute_next_change(time: Field) -> Field { ((time as u120 / EPOCH_LENGTH + 1) * EPOCH_LENGTH) as Field } +// TODO(#4760): Rename slow updates to shared mutable and ideally move the impl to state-vars in aztec-nr. // The simple slow map which stores a sparse tree struct SlowMap { context: Context, diff --git a/noir-projects/aztec-nr/value-note/src/balance_utils.nr b/noir-projects/aztec-nr/value-note/src/balance_utils.nr index 6372d718902..74cba0e9679 100644 --- a/noir-projects/aztec-nr/value-note/src/balance_utils.nr +++ b/noir-projects/aztec-nr/value-note/src/balance_utils.nr @@ -1,12 +1,12 @@ use dep::aztec::note::{note_getter::view_notes, note_viewer_options::NoteViewerOptions}; -use dep::aztec::state_vars::set::Set; +use dep::aztec::state_vars::PrivateSet; use crate::value_note::ValueNote; -unconstrained pub fn get_balance(set: Set) -> Field { +unconstrained pub fn get_balance(set: PrivateSet) -> Field { get_balance_with_offset(set, 0) } -unconstrained pub fn get_balance_with_offset(set: Set, offset: u32) -> Field { +unconstrained pub fn get_balance_with_offset(set: PrivateSet, offset: u32) -> Field { let mut balance = 0; // docs:start:view_notes let options = NoteViewerOptions::new().set_offset(offset); diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index d7ef7c948dc..af4eacb7680 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -2,7 +2,7 @@ use dep::std::option::Option; use dep::aztec::context::PrivateContext; use dep::aztec::note::note_getter_options::{NoteGetterOptions, SortOrder}; use dep::aztec::oracle::get_public_key::get_public_key; -use dep::aztec::state_vars::set::Set; +use dep::aztec::state_vars::PrivateSet; use crate::{ filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN}, @@ -17,7 +17,7 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG // Creates a new note for the recipient. // Inserts it to the recipient's set of notes. -pub fn increment(balance: Set, amount: Field, recipient: AztecAddress) { +pub fn increment(balance: PrivateSet, amount: Field, recipient: AztecAddress) { let mut note = ValueNote::new(amount, recipient); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. balance.insert(&mut note, amount != 0); @@ -27,7 +27,7 @@ pub fn increment(balance: Set, amount: Field, recipient: AztecAddress // Remove those notes. // If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed. // Fail if the sum of the selected notes is less than the amount. -pub fn decrement(balance: Set, amount: Field, owner: AztecAddress) { +pub fn decrement(balance: PrivateSet, amount: Field, owner: AztecAddress) { let sum = decrement_by_at_most(balance, amount, owner); assert(sum == amount, "Balance too low"); } @@ -40,7 +40,7 @@ pub fn decrement(balance: Set, amount: Field, owner: AztecAddress) { // equal `amount`. // // It returns the decremented amount, which should be less than or equal to max_amount. -pub fn decrement_by_at_most(balance: Set, max_amount: Field, owner: AztecAddress) -> Field { +pub fn decrement_by_at_most(balance: PrivateSet, max_amount: Field, owner: AztecAddress) -> Field { let options = create_note_getter_options_for_decreasing_balance(max_amount); let opt_notes = balance.get_notes(options); @@ -64,7 +64,7 @@ pub fn decrement_by_at_most(balance: Set, max_amount: Field, owner: A // Removes the note from the owner's set of notes. // Returns the value of the destroyed note. -pub fn destroy_note(balance: Set, owner: AztecAddress, note: ValueNote) -> Field { +pub fn destroy_note(balance: PrivateSet, owner: AztecAddress, note: ValueNote) -> Field { // Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). assert(note.owner.eq(owner)); diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index 1e53fbfe4da..feee4ecfecc 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -11,20 +11,22 @@ contract AppSubscriptionContract { use dep::aztec::{ context::{PrivateContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, oracle::get_public_key::get_public_key, - state_vars::{map::Map, singleton::Singleton, public_state::PublicState, stable_public_state::StablePublicState} + state_vars::{Map, PrivateMutable, PublicMutable, SharedImmutable} }; use dep::authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}; use crate::subscription_note::{SubscriptionNote, SUBSCRIPTION_NOTE_LEN}; struct Storage { - // todo change this to immutable singletons because it's only needed in private - target_address: StablePublicState, - subscription_token_address: StablePublicState, - subscription_recipient_address: StablePublicState, - subscription_price: StablePublicState, - subscriptions: Map>, - gas_token_address: StablePublicState, + // The following is only needed in private but we use ShareImmutable here instead of PrivateImmutable because + // the value can be publicly known and SharedImmutable provides us with a better devex here because we don't + // have to bother with sharing the note between pixies of users. + target_address: SharedImmutable, + subscription_token_address: SharedImmutable, + subscription_recipient_address: SharedImmutable, + subscription_price: SharedImmutable, + subscriptions: Map>, + gas_token_address: SharedImmutable, } global SUBSCRIPTION_DURATION_IN_BLOCKS = 5; diff --git a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr index 86215deb334..4044cdd6920 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -11,12 +11,12 @@ contract Benchmarking { protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, context::{Context}, note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - log::emit_unencrypted_log, state_vars::{map::Map, public_state::PublicState, set::Set} + log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet} }; struct Storage { - notes: Map>, - balances: Map>, + notes: Map>, + balances: Map>, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index 6b3e694768b..7d5b997daa4 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -12,7 +12,7 @@ use dep::aztec::{ note_viewer_options::NoteViewerOptions, note_getter::view_notes, }, - state_vars::set::Set, + state_vars::PrivateSet, }; use dep::std; use dep::std::{ @@ -88,7 +88,7 @@ impl CardNote { } struct Deck { - set: Set, + set: PrivateSet, } pub fn filter_cards( @@ -122,7 +122,7 @@ impl Deck { context: Context, storage_slot: Field, ) -> Self { - let set = Set { + let set = PrivateSet { context, storage_slot, }; diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr index 8af2576846a..930215d7802 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr @@ -3,7 +3,7 @@ mod game; contract CardGame { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, constants::MAX_NOTES_PER_PAGE}; - use dep::aztec::{context::Context, hash::pedersen_hash, state_vars::{map::Map, public_state::PublicState}}; + use dep::aztec::{context::Context, hash::pedersen_hash, state_vars::{Map, PublicMutable}}; use dep::std::option::Option; use dep::value_note::{balance_utils, value_note::{ValueNote, VALUE_NOTE_LEN}}; @@ -16,7 +16,7 @@ contract CardGame { struct Storage { collections: Map, game_decks: Map>, - games: Map>, + games: Map>, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 8542bea1b84..315c4c7ec34 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -4,15 +4,15 @@ contract Child { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, log::emit_unencrypted_log, - state_vars::{public_state::PublicState, set::Set}, + state_vars::{PublicMutable, PrivateSet}, protocol_types::{abis::{function_selector::FunctionSelector, call_context::CallContext}, address::AztecAddress}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader, utils as note_utils} }; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; struct Storage { - current_value: PublicState, - a_private_value: Set, + current_value: PublicMutable, + a_private_value: PrivateSet, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr index 6cfad8ed21c..b6db63a8cc7 100644 --- a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr @@ -7,7 +7,7 @@ contract Counter { note_header::NoteHeader, utils as note_utils, }, - state_vars::map::Map, + state_vars::Map, }; use dep::value_note::{ balance_utils, diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index c1678eb1814..928760f048f 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -4,7 +4,7 @@ contract DelegatedOn { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, log::emit_unencrypted_log, - state_vars::{public_state::PublicState, set::Set}, + state_vars::{PublicMutable, PrivateSet}, protocol_types::{abis::{function_selector::FunctionSelector, call_context::CallContext}, address::AztecAddress}, note::{ note_getter_options::NoteGetterOptions, note_viewer_options::NoteViewerOptions, @@ -14,8 +14,8 @@ contract DelegatedOn { use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; struct Storage { - current_value: PublicState, - a_private_value: Set, + current_value: PublicMutable, + a_private_value: PrivateSet, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr index 64a6bfe8b14..d93629e4fea 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr @@ -3,15 +3,15 @@ contract Delegator { use dep::std::option::Option; use dep::aztec::{ - log::emit_unencrypted_log, state_vars::{public_state::PublicState, set::Set}, + log::emit_unencrypted_log, state_vars::{PublicMutable, PrivateSet}, protocol_types::{abis::{function_selector::FunctionSelector}, address::AztecAddress}, note::{note_viewer_options::NoteViewerOptions, utils as note_utils, note_header::NoteHeader} }; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; struct Storage { - current_value: PublicState, - a_private_value: Set, + current_value: PublicMutable, + a_private_value: PrivateSet, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index 7c555eea3b5..9e246f32e80 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -1,11 +1,11 @@ mod options; mod types; -// Following is a very simple game to show case use of singleton in as minimalistic way as possible -// It also serves as an e2e test that you can read and then replace the singleton in the same call +// Following is a very simple game to show case use of PrivateMutable in as minimalistic way as possible +// It also serves as an e2e test that you can read and then replace the PrivateMutable in the same call // (tests ordering in the circuit) -// you have a card (singleton). Anyone can create a bigger card. Whoever is bigger will be the leader. +// you have a card (PrivateMutable). Anyone can create a bigger card. Whoever is bigger will be the leader. // it also has dummy methods and other examples used for documentation e.g. // how to create custom notes, a custom struct for public state, a custom note that may be unencrypted // also has `options.nr` which shows various ways of using `NoteGetterOptions` to query notes @@ -25,7 +25,7 @@ contract DocsExample { utils as note_utils, }, context::{PrivateContext, PublicContext, Context}, - state_vars::{map::Map, public_state::PublicState,singleton::Singleton, immutable_singleton::ImmutableSingleton, set::Set, stable_public_state::StablePublicState}, + state_vars::{Map, PublicMutable, PrivateMutable, PrivateImmutable, PrivateSet, SharedImmutable}, }; // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; @@ -35,28 +35,26 @@ contract DocsExample { }; struct Storage { - // Shows how to create a custom struct in PublicState + // Shows how to create a custom struct in PublicMutable // docs:start:storage-leader-declaration - leader: PublicState, + leader: PublicMutable, // docs:end:storage-leader-declaration - // docs:start:storage-singleton-declaration - legendary_card: Singleton, - // docs:end:storage-singleton-declaration - // just used for docs example to show how to create a singleton map. - // docs:start:storage-map-singleton-declaration - profiles: Map>, - // docs:end:storage-map-singleton-declaration + // docs:start:storage-private-mutable-declaration + legendary_card: PrivateMutable, + // docs:end:storage-private-mutable-declaration + // just used for docs example to show how to create a private mutable map. + profiles: Map>, // docs:start:storage-set-declaration - set: Set, + set: PrivateSet, // docs:end:storage-set-declaration - // docs:start:storage-immutable-singleton-declaration - imm_singleton: ImmutableSingleton, - // docs:end:storage-immutable-singleton-declaration - // docs:start:storage-stable-declaration - stable_value: StablePublicState, - // docs:end:storage-stable-declaration + // docs:start:storage-private-immutable-declaration + private_immutable: PrivateImmutable, + // docs:end:storage-private-immutable-declaration + // docs:start:storage-shared-immutable-declaration + shared_immutable: SharedImmutable, + // docs:end:storage-shared-immutable-declaration // docs:start:storage-minters-declaration - minters: Map>, + minters: Map>, // docs:end:storage-minters-declaration } @@ -64,37 +62,37 @@ contract DocsExample { fn init(context: Context) -> Self { Storage { // docs:start:storage-leader-init - leader: PublicState::new( + leader: PublicMutable::new( context, 1 ), // docs:end:storage-leader-init - // docs:start:start_vars_singleton - legendary_card: Singleton::new(context, 3), - // docs:end:start_vars_singleton + // docs:start:start_vars_private_mutable + legendary_card: PrivateMutable::new(context, 3), + // docs:end:start_vars_private_mutable // just used for docs example (not for game play): - // docs:start:state_vars-MapSingleton + // docs:start:state_vars-MapPrivateMutable profiles: Map::new( context, 4, |context, slot| { - Singleton::new(context, slot) + PrivateMutable::new(context, slot) }, ), - // docs:end:state_vars-MapSingleton + // docs:end:state_vars-MapPrivateMutable // docs:start:storage-set-init - set: Set::new(context, 5), + set: PrivateSet::new(context, 5), // docs:end:storage-set-init - imm_singleton: ImmutableSingleton::new(context, 6), - // docs:start:storage-stable-init - stable_value: StablePublicState::new(context, 7), - // docs:end:storage-stable-init + private_immutable: PrivateImmutable::new(context, 6), + // docs:start:storage-shared-immutable + shared_immutable: SharedImmutable::new(context, 7), + // docs:end:storage-shared-immutable // docs:start:storage-minters-init minters: Map::new( context, 8, |context, slot| { - PublicState::new(context, slot) + PublicMutable::new(context, slot) }, ), // docs:end:storage-minters-init @@ -106,31 +104,31 @@ contract DocsExample { fn constructor() {} #[aztec(public)] - fn initialize_stable(points: u8) { + fn initialize_shared_immutable(points: u8) { let mut new_leader = Leader { account: context.msg_sender(), points }; - storage.stable_value.initialize(new_leader); + storage.shared_immutable.initialize(new_leader); } #[aztec(private)] - fn match_stable(account: AztecAddress, points: u8) { + fn match_shared_immutable(account: AztecAddress, points: u8) { let expected = Leader { account, points }; - let read = storage.stable_value.read_private(); + let read = storage.shared_immutable.read_private(); assert(read.account == expected.account, "Invalid account"); assert(read.points == expected.points, "Invalid points"); } - unconstrained fn get_stable() -> pub Leader { - storage.stable_value.read_public() + unconstrained fn get_shared_immutable() -> pub Leader { + storage.shared_immutable.read_public() } - // docs:start:initialize-immutable-singleton + // docs:start:initialize-private-mutable #[aztec(private)] - fn initialize_immutable_singleton(randomness: Field, points: u8) { + fn initialize_private_immutable(randomness: Field, points: u8) { let mut new_card = CardNote::new(points, randomness, context.msg_sender()); - storage.imm_singleton.initialize(&mut new_card, true); + storage.private_immutable.initialize(&mut new_card, true); } - // docs:end:initialize-immutable-singleton + // docs:end:initialize-private-mutable #[aztec(private)] // msg_sender() is 0 at deploy time. So created another function @@ -180,16 +178,16 @@ contract DocsExample { // Ensure `points` > current value // Also serves as a e2e test that you can `get_note()` and then `replace()` - // docs:start:state_vars-SingletonGet + // docs:start:state_vars-PrivateMutableGet let card = storage.legendary_card.get_note(false); - // docs:end:state_vars-SingletonGet + // docs:end:state_vars-PrivateMutableGet let points = card.points + 1; let mut new_card = CardNote::new(points, card.randomness, context.msg_sender()); - // docs:start:state_vars-SingletonReplace + // docs:start:state_vars-PrivateMutableReplace storage.legendary_card.replace(&mut new_card, true); - // docs:end:state_vars-SingletonReplace + // docs:end:state_vars-PrivateMutableReplace context.call_public_function( context.this_address(), @@ -212,24 +210,24 @@ contract DocsExample { storage.legendary_card.view_note() } - // docs:start:singleton_is_initialized + // docs:start:private_mutable_is_initialized unconstrained fn is_legendary_initialized() -> pub bool { storage.legendary_card.is_initialized() } - // docs:end:singleton_is_initialized + // docs:end:private_mutable_is_initialized - // docs:start:get_note-immutable-singleton + // docs:start:get_note-private-immutable unconstrained fn get_imm_card() -> pub CardNote { - storage.imm_singleton.get_note() + storage.private_immutable.get_note() } - // docs:end:get_note-immutable-singleton + // docs:end:get_note-private-immutable unconstrained fn view_imm_card() -> pub CardNote { - storage.imm_singleton.view_note() + storage.private_immutable.view_note() } - unconstrained fn is_imm_initialized() -> pub bool { - storage.imm_singleton.is_initialized() + unconstrained fn is_priv_imm_initialized() -> pub bool { + storage.private_immutable.is_initialized() } /// Macro equivalence section diff --git a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr index ed5091f485a..0d44ff2b3b3 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr @@ -6,7 +6,7 @@ contract EasyPrivateToken { note_header::NoteHeader, utils as note_utils, }, - state_vars::map::Map, + state_vars::Map, }; use dep::value_note::{ balance_utils, diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index f53586132a0..a6a388e6459 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -2,14 +2,14 @@ contract EasyPrivateVoting { // docs:start:imports use dep::aztec::{ protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, - context::{PrivateContext, Context}, state_vars::{map::Map, public_state::PublicState} + context::{PrivateContext, Context}, state_vars::{Map, PublicMutable} }; // docs:end:imports // docs:start:storage_struct struct Storage { - admin: PublicState, // admin can end vote - tally: Map>, // we will store candidate as key and number of votes as value - voteEnded: PublicState, // voteEnded is boolean + admin: PublicMutable, // admin can end vote + tally: Map>, // we will store candidate as key and number of votes as value + voteEnded: PublicMutable, // voteEnded is boolean } // docs:end:storage_struct diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index d53117493fb..f9dac6425b8 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -9,7 +9,7 @@ contract EcdsaAccount { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, oracle::get_public_key::get_public_key, - state_vars::immutable_singleton::ImmutableSingleton + state_vars::PrivateImmutable }; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, @@ -19,7 +19,7 @@ contract EcdsaAccount { use crate::ecdsa_public_key_note::EcdsaPublicKeyNote; struct Storage { - public_key: ImmutableSingleton, + public_key: PrivateImmutable, } global ACCOUNT_ACTIONS_STORAGE_SLOT = 2; diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr index d04a1599aea..f1fde13f770 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -7,13 +7,13 @@ contract Escrow { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader, utils as note_utils}, - oracle::get_public_key::get_public_key, state_vars::set::Set + oracle::get_public_key::get_public_key, state_vars::PrivateSet }; use dep::address_note::address_note::{AddressNote, ADDRESS_NOTE_LEN}; struct Storage { - owners: Set, + owners: PrivateSet, } // Creates a new instance diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index 2ae62fa96f3..c181caa1807 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -2,14 +2,14 @@ mod interfaces; contract FPC { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; - use dep::aztec::state_vars::stable_public_state::StablePublicState; + use dep::aztec::state_vars::SharedImmutable; use dep::safe_math::SafeU120; use crate::interfaces::Token; struct Storage { - other_asset: StablePublicState, - fee_asset: StablePublicState, + other_asset: SharedImmutable, + fee_asset: SharedImmutable, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index e34a44272fa..15a3ea7f62d 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -2,14 +2,14 @@ mod lib; contract GasToken { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; - use dep::aztec::{hash::{compute_secret_hash}, state_vars::{public_state::PublicState, map::Map}}; + use dep::aztec::{hash::{compute_secret_hash}, state_vars::{PublicMutable, Map}}; use dep::safe_math::SafeU120; use crate::lib::{calculate_fee, get_bridge_gas_msg_hash}; struct Storage { - balances: Map>, + balances: Map>, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index e737a47313c..1aa7f911ad9 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -5,7 +5,7 @@ contract InclusionProofs { grumpkin_point::GrumpkinPoint, contract_class_id::ContractClassId }; use dep::aztec::{ - state_vars::{map::Map, set::Set, public_state::PublicState}, context::Context, + state_vars::{Map, PrivateSet, PublicMutable}, context::Context, note::{ note_getter_options::NoteGetterOptions, note_getter_options::NoteStatus, note_header::NoteHeader, utils as note_utils @@ -31,9 +31,9 @@ contract InclusionProofs { use dep::value_note::value_note::ValueNote; // docs:end:value_note_imports struct Storage { - private_values: Map>, - public_value: PublicState, - public_unused_value: PublicState, + private_values: Map>, + public_value: PublicMutable, + public_unused_value: PublicMutable, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index 40c16ecf6f6..6f63a85e52c 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -20,8 +20,8 @@ contract Lending { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, state_vars::{ - map::Map, - public_state::PublicState, + Map, + PublicMutable, } }; use crate::asset::Asset; @@ -31,11 +31,11 @@ contract Lending { // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - collateral_asset: PublicState, - stable_coin: PublicState, - assets: Map>, - collateral: Map>, - static_debt: Map>, // abusing keys very heavily + collateral_asset: PublicMutable, + stable_coin: PublicMutable, + assets: Map>, + collateral: Map>, + static_debt: Map>, // abusing keys very heavily } struct Position { diff --git a/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr index 894fccf454c..fae26b23fc9 100644 --- a/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr @@ -9,12 +9,12 @@ contract PendingCommitments { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, log::emit_encrypted_log, note::{note_getter::NoteGetterOptions, note_header::NoteHeader, utils as note_utils}, - state_vars::{map::Map, set::Set} + state_vars::{Map, PrivateSet} }; use dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector}; struct Storage { - balances: Map>, + balances: Map>, } // TODO(dbanks12): consolidate code into internal helper functions diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr index a86fcc73bfd..dd9a743ed3c 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr @@ -5,8 +5,8 @@ contract PriceFeed { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, state_vars::{ - map::Map, - public_state::PublicState, + Map, + PublicMutable, }, }; use dep::aztec::protocol_types::address::AztecAddress; @@ -14,7 +14,7 @@ contract PriceFeed { // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - assets: Map>, + assets: Map>, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 1539c038b4a..6e4eec425c9 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -10,7 +10,7 @@ contract SchnorrAccount { use dep::aztec::{ context::{PrivateContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, - oracle::get_public_key::get_public_key, state_vars::immutable_singleton::ImmutableSingleton + oracle::get_public_key::get_public_key, state_vars::PrivateImmutable }; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, @@ -21,7 +21,7 @@ contract SchnorrAccount { struct Storage { // docs:start:storage - signing_public_key: ImmutableSingleton, + signing_public_key: PrivateImmutable, // docs:end:storage } diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr index 5ae8795d957..e930be53d75 100644 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr @@ -5,6 +5,7 @@ mod types; // More documentation need to be outlined for this properly, but there is some in // https://github.com/AztecProtocol/aztec-packages/issues/1291 // This is made as a separate contract for one thing mainly. Making it simpler to use. +// TODO(#4760): Rename slow updates to shared mutable and ideally move the impl to state-vars in aztec-nr. contract SlowTree { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; use dep::std::option::Option; @@ -12,7 +13,7 @@ contract SlowTree { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, - state_vars::{map::Map, public_state::PublicState, set::Set}, + state_vars::{Map, PublicMutable, PrivateSet}, protocol_types::type_serialization::FIELD_SERIALIZED_LEN }; use dep::slow_updates_tree::{SlowMap, Leaf, SlowUpdateProof, compute_merkle_root, deserialize_slow_update_proof}; diff --git a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr index b276253718f..62393469d9a 100644 --- a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -6,12 +6,12 @@ contract StatefulTest { use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, - state_vars::{map::Map, public_state::PublicState, set::Set} + state_vars::{Map, PublicMutable, PrivateSet} }; struct Storage { - notes: Map>, - public_values: Map>, + notes: Map>, + public_values: Map>, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 681f93b7dd1..90228a29b91 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -19,7 +19,7 @@ contract Test { note_viewer_options::NoteViewerOptions }, oracle::{get_public_key::get_public_key as get_public_key_oracle, context::get_portal_address, rand::rand}, - state_vars::immutable_singleton::ImmutableSingleton, log::emit_unencrypted_log_from_private + state_vars::PrivateImmutable, log::emit_unencrypted_log_from_private }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::field_note::field_note::FieldNote; @@ -31,7 +31,7 @@ contract Test { } struct Storage { - example_constant: ImmutableSingleton, + example_constant: PrivateImmutable, } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 92cb8dbab85..29c8bff7c70 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -29,7 +29,7 @@ contract TokenBlacklist { }, context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, - state_vars::{map::Map, public_state::PublicState, set::Set, immutable_singleton::ImmutableSingleton}, + state_vars::{Map, PublicMutable, PrivateSet, PrivateImmutable}, }; use dep::field_note::field_note::FieldNote; @@ -52,13 +52,13 @@ contract TokenBlacklist { // docs:end:interface struct Storage { - admin: PublicState, + admin: PublicMutable, balances: BalancesMap, - total_supply: PublicState, - pending_shields: Set, - public_balances: Map>, - slow_update: ImmutableSingleton, - public_slow_update: PublicState, + total_supply: PublicMutable, + pending_shields: PrivateSet, + public_balances: Map>, + slow_update: PrivateImmutable, + public_slow_update: PublicMutable, } // docs:start:constructor diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index cbc423cc4ff..b6ba0ef697e 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -2,7 +2,7 @@ use dep::std::option::Option; use dep::safe_math::SafeU120; use dep::aztec::{ context::Context, protocol_types::{address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL}, - state_vars::{set::Set, map::Map}, + state_vars::{PrivateSet, Map}, note::{ note_getter::view_notes, note_getter_options::{NoteGetterOptions, SortOrder}, note_viewer_options::NoteViewerOptions, note_header::NoteHeader, note_interface::NoteInterface @@ -11,13 +11,19 @@ use dep::aztec::{ use crate::types::token_note::{TokenNote, OwnedNote}; struct BalancesMap { - map: Map> + map: Map> } impl BalancesMap { pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - Self { map: Map::new(context, storage_slot, |context, slot| Set::new(context, slot)) } + Self { + map: Map::new( + context, + storage_slot, + |context, slot| PrivateSet::new(context, slot) + ) + } } unconstrained pub fn balance_of( diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index a7e2a45f1ec..1c9ddb96e3b 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,7 +1,7 @@ use dep::aztec::{ protocol_types::{address::AztecAddress, constants::{MAX_READ_REQUESTS_PER_CALL}}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - context::PrivateContext, state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash + context::PrivateContext, log::emit_encrypted_log, hash::pedersen_hash }; use dep::aztec::oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; use dep::safe_math::SafeU120; diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index a542c1846fa..8a00972b733 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -9,7 +9,7 @@ mod token_interface; contract TokenBridge { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; - use dep::aztec::{context::{Context}, hash::{compute_secret_hash}, state_vars::{public_state::PublicState}}; + use dep::aztec::{context::{Context}, hash::{compute_secret_hash}, state_vars::{PublicMutable}}; use dep::token_portal_content_hash_lib::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash}; @@ -19,7 +19,7 @@ contract TokenBridge { // docs:start:token_bridge_storage_and_constructor // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - token: PublicState, + token: PublicMutable, } // Constructs the contract. diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 6f0dfcbe9e2..6c2f351a97f 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -23,7 +23,7 @@ contract Token { utils as note_utils, }, hash::{compute_secret_hash}, - state_vars::{map::Map, public_state::PublicState, stable_public_state::StablePublicState, set::Set}, + state_vars::{Map, PublicMutable, SharedImmutable, PrivateSet}, protocol_types::{ abis::function_selector::FunctionSelector, address::AztecAddress @@ -49,23 +49,23 @@ contract Token { // docs:start:storage_struct struct Storage { // docs:start:storage_admin - admin: PublicState, + admin: PublicMutable, // docs:end:storage_admin // docs:start:storage_minters - minters: Map>, + minters: Map>, // docs:end:storage_minters // docs:start:storage_balances balances: BalancesMap, // docs:end:storage_balances - total_supply: PublicState, + total_supply: PublicMutable, // docs:start:storage_pending_shields - pending_shields: Set, + pending_shields: PrivateSet, // docs:end:storage_pending_shields - public_balances: Map>, - symbol: StablePublicState, - name: StablePublicState, + public_balances: Map>, + symbol: SharedImmutable, + name: SharedImmutable, // docs:start:storage_decimals - decimals: StablePublicState, + decimals: SharedImmutable, // docs:end:storage_decimals } // docs:end:storage_struct diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index a47fdce4f3f..7e868cdf513 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -3,7 +3,7 @@ use dep::safe_math::SafeU120; use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, hash::pedersen_hash, protocol_types::{address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL}, - state_vars::{set::Set, map::Map}, + state_vars::{PrivateSet, Map}, note::{ note_getter::view_notes, note_getter_options::{NoteGetterOptions, SortOrder}, note_viewer_options::NoteViewerOptions, note_header::NoteHeader, note_interface::NoteInterface @@ -12,13 +12,19 @@ use dep::aztec::{ use crate::types::token_note::{TokenNote, OwnedNote}; struct BalancesMap { - map: Map> + map: Map> } impl BalancesMap { pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - Self { map: Map::new(context, storage_slot, |context, slot| Set::new(context, slot)) } + Self { + map: Map::new( + context, + storage_slot, + |context, slot| PrivateSet::new(context, slot) + ) + } } unconstrained pub fn balance_of( diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 2be2ecb3e00..0039ad02257 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -1,7 +1,7 @@ use dep::aztec::{ protocol_types::{address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - context::PrivateContext, state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash + context::PrivateContext, log::emit_encrypted_log, hash::pedersen_hash }; use dep::aztec::oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; use dep::safe_math::SafeU120; diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index 311c0e349e8..f92dddff2f2 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -7,7 +7,7 @@ mod util; // Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 contract Uniswap { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; - use dep::aztec::{oracle::{context::get_portal_address}, state_vars::{map::Map, public_state::PublicState}}; + use dep::aztec::{oracle::{context::get_portal_address}, state_vars::{Map, PublicMutable}}; use dep::authwit::auth::{IS_VALID_SELECTOR, assert_current_call_valid_authwit_public, compute_authwit_message_hash}; @@ -16,10 +16,10 @@ contract Uniswap { struct Storage { // like with account contracts, stores the approval message on a slot and tracks if they are active - approved_action: Map>, + approved_action: Map>, // tracks the nonce used to create the approval message for burning funds // gets incremented each time after use to prevent replay attacks - nonce_for_burn_approval: PublicState, + nonce_for_burn_approval: PublicMutable, } #[aztec(private)] diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr index be81885d059..c5938e87500 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr @@ -93,11 +93,15 @@ global L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH: Field = 12; // MISC CONSTANTS global FUNCTION_SELECTOR_NUM_BYTES: Field = 4; -global MAPPING_SLOT_PEDERSEN_SEPARATOR: Field = 4; // sha256 hash is stored in two fields to accommodate all 256-bits of the hash global NUM_FIELDS_PER_SHA256: Field = 2; global ARGS_HASH_CHUNK_LENGTH: u32 = 32; global ARGS_HASH_CHUNK_COUNT: u32 = 32; +// The following is used in immutable state variables to compute an initialization slot whose value is used to +// determine whether a given variable has been initialized (by asserting that the value in the slot is 0). +// The initialization slot is computed by adding the constant bellow to the variable's storage slot. This constant has +// to be large enough so that it's ensured that it doesn't collide with storage slots of other variables. +global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; // CONTRACT CLASS CONSTANTS // This should be around 8192 (assuming 2**15 instructions packed at 8 bytes each), diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 8f70d5b5e86..91efd74ddaa 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -840,8 +840,8 @@ fn get_serialized_length( && !interner.lookup_all_trait_implementations(stored_in_state, trait_id).is_empty() }); - // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicState for whatever reason though. - if struct_name == "Map" || (is_note && struct_name != "PublicState") { + // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. + if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { return Ok(1); } diff --git a/noir/test_programs/execution_success/1327_concrete_in_generic/src/main.nr b/noir/test_programs/execution_success/1327_concrete_in_generic/src/main.nr index e1d601b13c9..3e476107c29 100644 --- a/noir/test_programs/execution_success/1327_concrete_in_generic/src/main.nr +++ b/noir/test_programs/execution_success/1327_concrete_in_generic/src/main.nr @@ -10,31 +10,31 @@ struct B { } impl B { - fn new(new_concrete_t_c_constructor: fn () -> T_C) -> B { - B { new_concrete_t_c_constructor } - } + fn new(new_concrete_t_c_constructor: fn() -> T_C) -> B { + B { new_concrete_t_c_constructor } + } - fn get_t_c(self) -> T_C { - let new_concrete_t_c_constructor = self.new_concrete_t_c_constructor; - new_concrete_t_c_constructor() - } + fn get_t_c(self) -> T_C { + let new_concrete_t_c_constructor = self.new_concrete_t_c_constructor; + new_concrete_t_c_constructor() } +} // --- -// Set +// PrivateSet struct C { t_d_interface: MethodInterface, } impl C { - fn new (t_d_interface: MethodInterface) -> Self { - C { t_d_interface } - } + fn new(t_d_interface: MethodInterface) -> Self { + C { t_d_interface } + } - fn call_method_of_t_d(self, t_d: T_D) -> Field { - let some_method_on_t_d = self.t_d_interface.some_method_on_t_d; - some_method_on_t_d(t_d) - } + fn call_method_of_t_d(self, t_d: T_D) -> Field { + let some_method_on_t_d = self.t_d_interface.some_method_on_t_d; + some_method_on_t_d(t_d) } +} // --- struct MethodInterface { some_method_on_t_d: fn(T_D)->Field, @@ -55,7 +55,7 @@ fn get_d_method_interface() -> MethodInterface { // --- fn main(input: Field) -> pub Field { let b: B> = B::new(new_concrete_c_over_d); - let c: C = b.get_t_c(); // Singleton + let c: C = b.get_t_c(); // PrivateMutable let d: D = D { d: input }; // Note let output = c.call_method_of_t_d(d); diff --git a/noir/test_programs/execution_success/regression_4124/src/main.nr b/noir/test_programs/execution_success/regression_4124/src/main.nr index b47bf28d461..49ff68ee6ad 100644 --- a/noir/test_programs/execution_success/regression_4124/src/main.nr +++ b/noir/test_programs/execution_success/regression_4124/src/main.nr @@ -14,14 +14,14 @@ pub fn storage_read() -> [Field; N] { dep::std::unsafe::zeroed() } -struct PublicState { +struct PublicMutable { storage_slot: Field, } -impl PublicState { +impl PublicMutable { pub fn new(storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - PublicState { storage_slot } + PublicMutable { storage_slot } } pub fn read(_self: Self) -> T where T: MyDeserialize { @@ -32,7 +32,7 @@ impl PublicState { } fn main(value: Field) { - let ps: PublicState = PublicState::new(27); + let ps: PublicMutable = PublicMutable::new(27); // error here assert(ps.read() == value); diff --git a/noir/tooling/nargo_fmt/tests/expected/contract.nr b/noir/tooling/nargo_fmt/tests/expected/contract.nr index 226667619f5..a03b8774700 100644 --- a/noir/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/tooling/nargo_fmt/tests/expected/contract.nr @@ -10,14 +10,14 @@ contract Benchmarking { use dep::aztec::{ context::{Context}, note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - log::emit_unencrypted_log, state_vars::{map::Map, public_state::PublicState, set::Set}, + log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, types::address::{AztecAddress} }; struct Storage { - notes: Map>, - balances: Map>, + notes: Map>, + balances: Map>, } impl Storage { @@ -26,12 +26,12 @@ contract Benchmarking { notes: Map::new( context, 1, - |context, slot| { Set::new(context, slot, ValueNoteMethods) } + |context, slot| { PrivateSet::new(context, slot, ValueNoteMethods) } ), balances: Map::new( context, 2, - |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) } + |context, slot| { PublicMutable::new(context, slot, FieldSerializationMethods) } ) } } diff --git a/noir/tooling/nargo_fmt/tests/input/contract.nr b/noir/tooling/nargo_fmt/tests/input/contract.nr index f863a9dc955..a03b8774700 100644 --- a/noir/tooling/nargo_fmt/tests/input/contract.nr +++ b/noir/tooling/nargo_fmt/tests/input/contract.nr @@ -5,30 +5,34 @@ contract Benchmarking { use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; - use dep::value_note::{ - utils::{increment, decrement}, - value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, - }; + use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; use dep::aztec::{ context::{Context}, note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - log::emit_unencrypted_log, - state_vars::{map::Map, public_state::PublicState, set::Set}, + log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - types::address::{AztecAddress}, + types::address::{AztecAddress} }; struct Storage { - notes: Map>, - balances: Map>, + notes: Map>, + balances: Map>, } impl Storage { fn init(context: Context) -> pub Self { Storage { - notes: Map::new(context, 1, |context, slot| { Set::new(context, slot, ValueNoteMethods) }), - balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) }), + notes: Map::new( + context, + 1, + |context, slot| { PrivateSet::new(context, slot, ValueNoteMethods) } + ), + balances: Map::new( + context, + 2, + |context, slot| { PublicMutable::new(context, slot, FieldSerializationMethods) } + ) } } } diff --git a/yarn-project/circuits.js/fixtures/Benchmarking.test.json b/yarn-project/circuits.js/fixtures/Benchmarking.test.json index 6bd40d7241c..4ee8cebbe8b 100644 --- a/yarn-project/circuits.js/fixtures/Benchmarking.test.json +++ b/yarn-project/circuits.js/fixtures/Benchmarking.test.json @@ -3404,8 +3404,8 @@ "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/map.nr" }, "50": { - "source": "use crate::context::{Context};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse crate::types::type_serialization::TypeSerializationInterface;\nuse dep::std::option::Option;\n\n// docs:start:public_state_struct\nstruct PublicState {\n context: Context,\n storage_slot: Field,\n serialization_methods: TypeSerializationInterface,\n}\n// docs:end:public_state_struct\n\nimpl PublicState {\n // docs:start:public_state_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field,\n serialization_methods: TypeSerializationInterface,\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicState {\n context,\n storage_slot,\n serialization_methods,\n }\n }\n // docs:end:public_state_struct_new\n\n // docs:start:public_state_struct_read\n pub fn read(self) -> T {\n assert(self.context.private.is_none(), \"Public state reads only supported in public functions\");\n storage_read(self.storage_slot, self.serialization_methods.deserialize)\n }\n // docs:end:public_state_struct_read\n\n // docs:start:public_state_struct_write\n pub fn write(self, value: T) {\n assert(self.context.private.is_none(), \"Public state writes only supported in public functions\");\n let serialize = self.serialization_methods.serialize;\n let fields = serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_state_struct_write\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/public_state.nr" + "source": "use crate::context::{Context};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse crate::types::type_serialization::TypeSerializationInterface;\nuse dep::std::option::Option;\n\n// docs:start:public_mutable_struct\nstruct PublicState {\n context: Context,\n storage_slot: Field,\n serialization_methods: TypeSerializationInterface,\n}\n// docs:end:public_mutable_struct\n\nimpl PublicState {\n // docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field,\n serialization_methods: TypeSerializationInterface,\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicState {\n context,\n storage_slot,\n serialization_methods,\n }\n }\n // docs:end:public_mutable_struct_new\n\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T {\n assert(self.context.private.is_none(), \"Public state reads only supported in public functions\");\n storage_read(self.storage_slot, self.serialization_methods.deserialize)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) {\n assert(self.context.private.is_none(), \"Public state writes only supported in public functions\");\n let serialize = self.serialization_methods.serialize;\n let fields = serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n", + "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/public_mutable.nr" }, "56": { "source": "#[oracle(storageRead)]\nfn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field, deserialize: fn([Field; N]) -> T) -> T {\n let fields = storage_read_oracle_wrapper(storage_slot);\n deserialize(fields)\n}\n\n#[oracle(storageWrite)]\nfn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\n// TODO: Remove return value.\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n", diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 47bbff17361..776afeed222 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -55,7 +55,6 @@ export const PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH = 35; export const L1_TO_L2_MSG_SUBTREE_HEIGHT = 4; export const L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH = 12; export const FUNCTION_SELECTOR_NUM_BYTES = 4; -export const MAPPING_SLOT_PEDERSEN_SEPARATOR = 4; export const NUM_FIELDS_PER_SHA256 = 2; export const ARGS_HASH_CHUNK_LENGTH = 32; export const ARGS_HASH_CHUNK_COUNT = 32; diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index ef720e7ca05..6365d289bc4 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -19,31 +19,39 @@ describe('e2e_state_vars', () => { afterAll(() => teardown()); - describe('Stable Public State', () => { - it('private read of uninitialized stable', async () => { - const s = await contract.methods.get_stable().view(); + describe('SharedImmutable', () => { + it('private read of uninitialized SharedImmutable', async () => { + const s = await contract.methods.get_shared_immutable().view(); - const receipt2 = await contract.methods.match_stable(s.account, s.points).send().wait(); + const receipt2 = await contract.methods.match_shared_immutable(s.account, s.points).send().wait(); expect(receipt2.status).toEqual(TxStatus.MINED); }); - it('private read of initialized stable', async () => { - const receipt = await contract.methods.initialize_stable(1).send().wait(); + it('private read of initialized SharedImmutable', async () => { + const receipt = await contract.methods.initialize_shared_immutable(1).send().wait(); expect(receipt.status).toEqual(TxStatus.MINED); - const s = await contract.methods.get_stable().view(); + const s = await contract.methods.get_shared_immutable().view(); - const receipt2 = await contract.methods.match_stable(s.account, s.points).send().wait(); + const receipt2 = await contract.methods.match_shared_immutable(s.account, s.points).send().wait(); expect(receipt2.status).toEqual(TxStatus.MINED); }, 200_000); + + it('initializing SharedImmutable the second time should fail', async () => { + // Jest executes the tests sequentially and the first call to initialize_shared_immutable was executed + // in the previous test, so the call bellow should fail. + await expect(contract.methods.initialize_shared_immutable(1).send().wait()).rejects.toThrowError( + "Assertion failed: SharedImmutable already initialized 'fields_read[0] == 0'", + ); + }, 100_000); }); - describe('Singleton', () => { - it('fail to read uninitialized singleton', async () => { + describe('PrivateMutable', () => { + it('fail to read uninitialized PrivateMutable', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(false); await expect(contract.methods.get_legendary_card().view()).rejects.toThrowError(); }); - it('initialize singleton', async () => { + it('initialize PrivateMutable', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(false); const receipt = await contract.methods.initialize_private(RANDOMNESS, POINTS).send().wait(); expect(receipt.status).toEqual(TxStatus.MINED); @@ -61,7 +69,7 @@ describe('e2e_state_vars', () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(true); }); - it('read initialized singleton', async () => { + it('read initialized PrivateMutable', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(true); const { points, randomness } = await contract.methods.get_legendary_card().view(); expect(points).toEqual(POINTS); @@ -91,7 +99,7 @@ describe('e2e_state_vars', () => { expect(noteBefore.header.nonce).not.toEqual(noteAfter.header.nonce); }); - it('replace singleton with other values', async () => { + it('replace PrivateMutable with other values', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(true); const receipt = await contract.methods .update_legendary_card(RANDOMNESS + 2n, POINTS + 1n) @@ -108,7 +116,7 @@ describe('e2e_state_vars', () => { expect(randomness).toEqual(RANDOMNESS + 2n); }); - it('replace singleton dependent on prior value', async () => { + it('replace PrivateMutable dependent on prior value', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(true); const noteBefore = await contract.methods.get_legendary_card().view(); const receipt = await contract.methods.increase_legendary_points().send().wait(); @@ -124,34 +132,34 @@ describe('e2e_state_vars', () => { }); }); - describe('Immutable Singleton', () => { - it('fail to read uninitialized singleton', async () => { - expect(await contract.methods.is_imm_initialized().view()).toEqual(false); + describe('PrivateImmutable', () => { + it('fail to read uninitialized PrivateImmutable', async () => { + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(false); await expect(contract.methods.view_imm_card().view()).rejects.toThrowError(); }); - it('initialize singleton', async () => { - expect(await contract.methods.is_imm_initialized().view()).toEqual(false); - const receipt = await contract.methods.initialize_immutable_singleton(RANDOMNESS, POINTS).send().wait(); + it('initialize PrivateImmutable', async () => { + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(false); + const receipt = await contract.methods.initialize_private_immutable(RANDOMNESS, POINTS).send().wait(); expect(receipt.status).toEqual(TxStatus.MINED); const tx = await wallet.getTx(receipt.txHash); expect(tx?.newNoteHashes.length).toEqual(1); // 1 for the tx, another for the initializer expect(tx?.newNullifiers.length).toEqual(2); - expect(await contract.methods.is_imm_initialized().view()).toEqual(true); + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(true); }); it('fail to reinitialize', async () => { - expect(await contract.methods.is_imm_initialized().view()).toEqual(true); + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(true); await expect( - contract.methods.initialize_immutable_singleton(RANDOMNESS, POINTS).send().wait(), + contract.methods.initialize_private_immutable(RANDOMNESS, POINTS).send().wait(), ).rejects.toThrowError(); - expect(await contract.methods.is_imm_initialized().view()).toEqual(true); + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(true); }); - it('read initialized singleton', async () => { - expect(await contract.methods.is_imm_initialized().view()).toEqual(true); + it('read initialized PrivateImmutable', async () => { + expect(await contract.methods.is_priv_imm_initialized().view()).toEqual(true); const { points, randomness } = await contract.methods.view_imm_card().view(); expect(points).toEqual(POINTS); expect(randomness).toEqual(RANDOMNESS);