From 64e0d10314e13acc9c42da5683b57fcdb025fee1 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 19 Sep 2023 21:00:54 +0000 Subject: [PATCH 1/7] chore: misc changes to docs --- docs/docs/dev_docs/contracts/aztec_types.md | 16 ++ .../dev_docs/contracts/syntax/context.mdx | 2 +- .../dev_docs/contracts/syntax/contract.md | 23 +- .../dev_docs/contracts/syntax/functions.md | 10 + .../docs/dev_docs/contracts/syntax/storage.md | 31 ++- docs/docs/dev_docs/limitations/main.md | 16 +- docs/sidebars.js | 246 +++++++++--------- .../docs_example_contract/src/main.nr | 4 +- 8 files changed, 203 insertions(+), 145 deletions(-) create mode 100644 docs/docs/dev_docs/contracts/aztec_types.md diff --git a/docs/docs/dev_docs/contracts/aztec_types.md b/docs/docs/dev_docs/contracts/aztec_types.md new file mode 100644 index 00000000000..ca73d7ab5b2 --- /dev/null +++ b/docs/docs/dev_docs/contracts/aztec_types.md @@ -0,0 +1,16 @@ +--- +title: Aztec.nr Types +description: Documentation of Aztec's Types +--- + +With Aztec.nr we are include a series of types that are useful for writing Aztec contracts. While almost anything is modelled just as plain Fields underneath it can be quite useful for developers to have a series of types when writing that apply different types of constrains on top to make the code more readable and easier to follow. + +## `AztecAddress` + +A wrapper around a Field that mainly just alters the name to make it more clear that the value is an address and not a number of a hash or something else. + +## `EthereumAddress` + +A wrapper around a Field that perform a range check to ensure that the number of bytes used don't exceed 20. + + diff --git a/docs/docs/dev_docs/contracts/syntax/context.mdx b/docs/docs/dev_docs/contracts/syntax/context.mdx index 3ea5a60ab16..3b8afffd983 100644 --- a/docs/docs/dev_docs/contracts/syntax/context.mdx +++ b/docs/docs/dev_docs/contracts/syntax/context.mdx @@ -1,5 +1,5 @@ --- -title: Aztec.nr Context +title: Function Context description: Documentation of Aztec's Private and Public execution contexts hide_table_of_contents: false --- diff --git a/docs/docs/dev_docs/contracts/syntax/contract.md b/docs/docs/dev_docs/contracts/syntax/contract.md index 5e125b8a797..7091ec63c5f 100644 --- a/docs/docs/dev_docs/contracts/syntax/contract.md +++ b/docs/docs/dev_docs/contracts/syntax/contract.md @@ -1,10 +1,10 @@ --- -title: Contract +title: Structure --- # Contract -A contract is a collection of persistent [state variables](./state_variables.md), and [functions](./functions) which may modify these persistent states. Functions and states within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. +A contract is a collection of persistent [state variables](./state_variables.md), and [functions](./functions) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. A contract may be declared and given a name using the `contract` keyword (see snippet below). By convention, contracts are named in `PascalCase`. @@ -12,20 +12,15 @@ A contract may be declared and given a name using the `contract` keyword (see sn // highlight-next-line contract MyContract { - // Functions and state variables belonging to this contract are not shown here. + // Imports + // Storage + + // Functions } ``` - -> A note for vanilla Noir devs: There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). - -## Structure of a contract - -- Private state variables -- Public state variables -- Private functions -- Public functions -- Encrypted events -- Unencrypted events +:::info A note for vanilla Noir devs +There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). +::: You can review the structure of a complete contract in the token contract tutorial [here](../../getting_started/token_contract_tutorial.md). diff --git a/docs/docs/dev_docs/contracts/syntax/functions.md b/docs/docs/dev_docs/contracts/syntax/functions.md index b68c18e515f..9c8e1b24e00 100644 --- a/docs/docs/dev_docs/contracts/syntax/functions.md +++ b/docs/docs/dev_docs/contracts/syntax/functions.md @@ -1,5 +1,6 @@ --- title: Functions +description: This page will go over functions, how private and public functions differ and how then can be used together. --- @@ -23,6 +24,15 @@ A good place to use `internal` is when you want a private function to be able to Note that non-internal functions could be used directly as an entry-point, which currently means that the `msg_sender` would be `0`, so for now, using address `0` as a burn address is not recommended. ::: +## Mutability +Currently, any function is "mutable" in the sense that it might alter state. In the future, we will support static calls, similarly to EVM. A static call is essentially a call that does not alter state (it keeps state static). This is useful for when you want to call a function in a separate contract, but ensure that it cannot alter state, or call other functions that might alter state (such as re-entering). + +Similarly, a special case of a mutating call is the `delegatecall` where the function executed might not be in the same contract as the state being altered. It is at this moment, not certain if `delegatecall`s should become a fully fledged feature. + +:::danger No `staticcall` or `delegatecall` support +While `staticcall` and `delegatecall` both have flags in the call context, they are currently not supported and will not behave as one would expect if usage is attempted. +::: + ## `constructor` - A special `constructor` function MUST be declared within a contract's scope. diff --git a/docs/docs/dev_docs/contracts/syntax/storage.md b/docs/docs/dev_docs/contracts/syntax/storage.md index 2ef2b361037..e809aa1faf7 100644 --- a/docs/docs/dev_docs/contracts/syntax/storage.md +++ b/docs/docs/dev_docs/contracts/syntax/storage.md @@ -1,13 +1,36 @@ # Storage -State variables must be declared inside a struct. (This enables us to declare types composed of nested generics in Noir). +In an Aztec.nr contract, storage is to be defined as a single struct. (This enables us to declare types composed of nested generics in Noir). -We could define any kinds of state variables in the Storage struct: +The struct **must** be called `Storage` for the Aztec.nr library to properly handle it (will be fixed in the future to support more flexibility). +An example of such a struct could be as follow: + +#include_code storage-struct-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust + +In here, we are setting up a mix of public and private state variables. The public state variables can be read by anyone, and functions manipulating them are executed by the sequence, we will see more to this in [functions](./functions.md#public-functions) in a few moments. The private state variables are only readable by their owner, or people whom the owner have shared the data with. + +As mentioned earlier in the foundational concepts ([state model](./../../../concepts/foundation/state_model.md) and [private/public execution](./../../../concepts/foundation/communication/public_private_calls.md)) private state are following a UTXO model where only the people knowing the pre-images of the commitments in the state will be able to use that knowledge. + +It is currently required to specify the length of the types when declaring the storage struct. The length will depend on the type of the state variable you are using with the length being the number of Field elements used to represent it. + +Since Aztec.nr is a library on top of Noir, we can use the types defined in Noir, so it can be useful to consult the [Noir documentation](https://noir-lang.org/language_concepts/data_types) for information on types. + +Currently, the sandbox also require that you specify how this storage struct is going to be initialized. Initialized here being how the state variables should be "setup" such that they can be read properly by the contract. This is done by specifying an `init` function that is run in functions that rely on reading or altering the state variables. + +An example of such a function for the above storage struct would be: #include_code storage-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust -See [State Variables](./state_variables.md) for how to initialise them. +:::warning Using slot `0` is not supported! +No storage values should be initialized at slot `0`. If you are using slot `0` for storage, you will not get an error when compiling, but the contract will not be updating the storage! This is a known bug that will be fixed in the future. +::: -Using Storage in a contract is like using any other struct in Noir. For each function that needs access to the storage, initialise the storage inside the function, and then access its state variable members: +In [State Variables](./state_variables.md) we will see in more detail what each of these types are, how they work and how to initialize them. + +To use the storage in functions, e.g., functions where you would read or write storage, you need to initialize the struct first, and then you can read and write afterwards. #include_code storage-init /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust + +:::info +https://github.com/AztecProtocol/aztec-packages/pull/2406 is removing the need to explicitly initialize the storage in each function before reading or writing. This will be updated in the docs once the PR is merged. +::: \ No newline at end of file diff --git a/docs/docs/dev_docs/limitations/main.md b/docs/docs/dev_docs/limitations/main.md index 7790b895cff..4b54fd87ea9 100644 --- a/docs/docs/dev_docs/limitations/main.md +++ b/docs/docs/dev_docs/limitations/main.md @@ -12,9 +12,6 @@ The Aztec Sandbox and the Aztec Smart Contract Library are **prototypes**, and s - An 'unpolished' UX; - Missing information. -## Why isn't it working perfectly yet? - -These things take time :) ## Why participate? @@ -29,6 +26,19 @@ Help shape and define: - Educational content; - Core protocol improvements; +## Limitations that devs need to know about +- It is a testing environment, it is insecure, unaudited and don't generate any proofs, its only for testing purposes; +- Constructor can't call or alter public state + - the constructor is completely executed in private domain, WITHOUT the ability to call public functions or alter public state. This means that to set initial storage values, you need to follow a pattern similar to proxies in Eth, where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions.md#constructor). +- No static or delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). + - there are values in the call-context, but they are not used. Beware that what you think of as a `view` could alter state ATM! Notable the account could alter state or re-enter whenever the account `is_valid` is called. +- `msg_sender` is leaked when doing private -> public calls + - the `msg_sender` will always be set, so if you call a public function from the private world, the `msg_sender` will be set to the private caller's address 😱, see [function context](../contracts/syntax/context.mdx). +- The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions.md#function-visibility). +- Unencrypted logs don't link to the contract that emitted it, so essentially just a `debug_log`` that you can match values against. +- A note that is created and nullified in the same transaction will still emit an encrypted log. +- A limited amount of new commitments, nullifiers and calls that are supported by a transaction, see [circuit limitations](#circuit-limitations). + ## Limitations There are plans to resolve all of the below. See also the [engineering roadmap](../../about_aztec/roadmap/engineering_roadmap.md). diff --git a/docs/sidebars.js b/docs/sidebars.js index b5424636ddf..84995d845b5 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -58,6 +58,125 @@ const sidebars = { value: '', }, + // SPECIFICATION + + { + type: "html", + className: "sidebar-title", + value: "Specification", + defaultStyle: true, + }, + + { + label: "Foundational Concepts", + type: "category", + link: { + type: "doc", + id: "concepts/foundation/main", + }, + items: [ + "concepts/foundation/state_model", + { + label: "Accounts", + type: "category", + link: { type: "doc", id: "concepts/foundation/accounts/main" }, + items: ["concepts/foundation/accounts/keys"], + }, + "concepts/foundation/contracts", + "concepts/foundation/transactions", + // "concepts/foundation/blocks", + // "concepts/foundation/globals", + { + label: "Communication", + type: "category", + link: { + type: "doc", + id: "concepts/foundation/communication/main", + }, + items: [ + "concepts/foundation/communication/public_private_calls", + "concepts/foundation/communication/cross_chain_calls", + ], + }, + // { + // label: "Nodes and Clients", + // type: "category", + // link: { + // type: "doc", + // id: "concepts/foundation/nodes_clients/main", + // }, + // items: [ + // "concepts/foundation/nodes_clients/execution_client", + // "concepts/foundation/nodes_clients/prover_client", + // "concepts/foundation/nodes_clients/sequencer_client", + // ], + // }, + // "concepts/foundation/block_production", + // "concepts/foundation/upgrade_mechanism", + ], + }, + + { + label: "Advanced Concepts", + type: "category", + link: { + type: "doc", + id: "concepts/advanced/main", + }, + items: [ + { + label: "Data Structures", + type: "category", + link: { + type: "doc", + id: "concepts/advanced/data_structures/main", + }, + items: [ + "concepts/advanced/data_structures/trees", + "concepts/advanced/data_structures/indexed_merkle_tree", + ], + }, + { + label: "Circuits", + type: "category", + link: { + type: "doc", + id: "concepts/advanced/circuits/main", + }, + items: [ + { + label: "Kernels", + type: "category", + link: { + type: "doc", + id: "concepts/advanced/circuits/kernels/main", + }, + items: [ + "concepts/advanced/circuits/kernels/private_kernel", + "concepts/advanced/circuits/kernels/public_kernel", + ], + }, + { + label: "Rollup Circuits", + type: "category", + link: { + type: "doc", + id: "concepts/advanced/circuits/rollup_circuits/main", + }, + items: [], + }, + ], + }, + "concepts/advanced/public_vm", + "concepts/advanced/contract_creation", + ], + }, + + { + type: "html", + value: '', + }, + // DEVELOPER DOCUMENTATION { @@ -242,130 +361,13 @@ const sidebars = { ], }, - { + /* { label: "Security Considerations", type: "category", - items: ["dev_docs/limitations/main", "dev_docs/privacy/main"], - }, - - { - type: "html", - value: '', - }, - - // SPECIFICATION - - { - type: "html", - className: "sidebar-title", - value: "Specification", - defaultStyle: true, - }, - - { - label: "Foundational Concepts", - type: "category", - link: { - type: "doc", - id: "concepts/foundation/main", - }, - items: [ - "concepts/foundation/state_model", - { - label: "Accounts", - type: "category", - link: { type: "doc", id: "concepts/foundation/accounts/main" }, - items: ["concepts/foundation/accounts/keys"], - }, - "concepts/foundation/contracts", - "concepts/foundation/transactions", - // "concepts/foundation/blocks", - // "concepts/foundation/globals", - { - label: "Communication", - type: "category", - link: { - type: "doc", - id: "concepts/foundation/communication/main", - }, - items: [ - "concepts/foundation/communication/public_private_calls", - "concepts/foundation/communication/cross_chain_calls", - ], - }, - // { - // label: "Nodes and Clients", - // type: "category", - // link: { - // type: "doc", - // id: "concepts/foundation/nodes_clients/main", - // }, - // items: [ - // "concepts/foundation/nodes_clients/execution_client", - // "concepts/foundation/nodes_clients/prover_client", - // "concepts/foundation/nodes_clients/sequencer_client", - // ], - // }, - // "concepts/foundation/block_production", - // "concepts/foundation/upgrade_mechanism", - ], - }, - - { - label: "Advanced Concepts", - type: "category", - link: { - type: "doc", - id: "concepts/advanced/main", - }, - items: [ - { - label: "Data Structures", - type: "category", - link: { - type: "doc", - id: "concepts/advanced/data_structures/main", - }, - items: [ - "concepts/advanced/data_structures/trees", - "concepts/advanced/data_structures/indexed_merkle_tree", - ], - }, - { - label: "Circuits", - type: "category", - link: { - type: "doc", - id: "concepts/advanced/circuits/main", - }, - items: [ - { - label: "Kernels", - type: "category", - link: { - type: "doc", - id: "concepts/advanced/circuits/kernels/main", - }, - items: [ - "concepts/advanced/circuits/kernels/private_kernel", - "concepts/advanced/circuits/kernels/public_kernel", - ], - }, - { - label: "Rollup Circuits", - type: "category", - link: { - type: "doc", - id: "concepts/advanced/circuits/rollup_circuits/main", - }, - items: [], - }, - ], - }, - "concepts/advanced/public_vm", - "concepts/advanced/contract_creation", - ], - }, + items: [], + },*/ + "dev_docs/privacy/main", + "dev_docs/limitations/main", { type: "html", diff --git a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr index 14af9b686e6..961de5cc9ae 100644 --- a/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr @@ -27,7 +27,7 @@ contract DocsExample { rules_note::{RulesNote, RulesNoteMethods, RULES_NOTE_LEN}, }; - // docs:start:storage-declaration + // docs:start:storage-struct-declaration struct Storage { locked: PublicState, queen: PublicState, @@ -36,7 +36,9 @@ contract DocsExample { cards: Set, profiles: Map>, } + // docs:end:storage-struct-declaration + // docs:start:storage-declaration // docs:start:state_vars-PublicState // docs:start:state_vars-PublicStateCustomStruct // docs:start:state_vars-Singleton From a26f4e3c4bba082913fc749bea74079575393926 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 19 Sep 2023 21:58:17 +0000 Subject: [PATCH 2/7] docs: small misc changes + ordering changes --- docs/docs/dev_docs/contracts/layout.md | 28 ++++++- .../dev_docs/contracts/syntax/contract.md | 26 ------- .../dev_docs/contracts/{ => syntax}/events.md | 78 ++++++++++--------- .../dev_docs/contracts/syntax/functions.md | 1 + .../docs/dev_docs/contracts/syntax/globals.md | 4 +- docs/docs/dev_docs/contracts/syntax/main.md | 4 +- .../docs/dev_docs/contracts/syntax/storage.md | 4 + docs/sidebars.js | 9 +-- .../src/contracts/token_contract/src/main.nr | 2 + 9 files changed, 81 insertions(+), 75 deletions(-) delete mode 100644 docs/docs/dev_docs/contracts/syntax/contract.md rename docs/docs/dev_docs/contracts/{ => syntax}/events.md (67%) diff --git a/docs/docs/dev_docs/contracts/layout.md b/docs/docs/dev_docs/contracts/layout.md index a6db7b63a6d..2e6420cf75d 100644 --- a/docs/docs/dev_docs/contracts/layout.md +++ b/docs/docs/dev_docs/contracts/layout.md @@ -1,4 +1,27 @@ -# Layout +--- +title: Structure +--- + +A contract is a collection of persistent [state variables](./syntax/state_variables.md), and [functions](./syntax/functions) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. + +# Contract + +A contract may be declared and given a name using the `contract` keyword (see snippet below). By convention, contracts are named in `PascalCase`. + +```rust title="contract keyword" +// highlight-next-line +contract MyContract { + + // Imports + + // Storage + + // Functions +} +``` +:::info A note for vanilla Noir devs +There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). +::: ## Directory structure @@ -11,4 +34,5 @@ Here's a common layout for a basic Aztec.nr Contract project: └── Nargo.toml <-- package and dependency management ``` -> See the vanilla Noir docs for [more info on packages](https://noir-lang.org/modules_packages_crates/crates_and_packages). +- See the vanilla Noir docs for [more info on packages](https://noir-lang.org/modules_packages_crates/crates_and_packages). +- You can review the structure of a complete contract in the token contract tutorial [here](../getting_started/token_contract_tutorial.md). diff --git a/docs/docs/dev_docs/contracts/syntax/contract.md b/docs/docs/dev_docs/contracts/syntax/contract.md deleted file mode 100644 index 7091ec63c5f..00000000000 --- a/docs/docs/dev_docs/contracts/syntax/contract.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Structure ---- - -# Contract - -A contract is a collection of persistent [state variables](./state_variables.md), and [functions](./functions) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. - -A contract may be declared and given a name using the `contract` keyword (see snippet below). By convention, contracts are named in `PascalCase`. - -```rust title="contract keyword" -// highlight-next-line -contract MyContract { - - // Imports - - // Storage - - // Functions -} -``` -:::info A note for vanilla Noir devs -There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). -::: - -You can review the structure of a complete contract in the token contract tutorial [here](../../getting_started/token_contract_tutorial.md). diff --git a/docs/docs/dev_docs/contracts/events.md b/docs/docs/dev_docs/contracts/syntax/events.md similarity index 67% rename from docs/docs/dev_docs/contracts/events.md rename to docs/docs/dev_docs/contracts/syntax/events.md index 36a809fde36..2c47231e139 100644 --- a/docs/docs/dev_docs/contracts/events.md +++ b/docs/docs/dev_docs/contracts/syntax/events.md @@ -5,12 +5,14 @@ title: Events Events in Aztec work similarly to Ethereum events in the sense that they are a way for contracts to communicate with the outside world. They are emitted by contracts and stored inside each instance of an AztecNode. -> Aztec events are currently represented as raw data and are not ABI encoded. -> ABI encoded events are a feature that will be added in the future. +:::info +Aztec events are currently represented as raw data and are not ABI encoded. +ABI encoded events are a feature that will be added in the future. +::: Unlike on Ethereum, there are 2 types of events supported by Aztec: encrypted and unencrypted. -### Encrypted Events +## Encrypted Events Encrypted events can only be emitted by private functions and are encrypted using a public key of a recipient. For this reason it is necessary to register a recipient in the Aztec RPC Server before encrypting the events for them. @@ -51,13 +53,15 @@ await aztecRpc.registerRecipient(completeAddress); -> **NOTE**: If a note recipient is one of the accounts inside the Aztec RPC Server, we don't need to register it as a recipient because we already have the public key available. +:::info +If a note recipient is one of the accounts inside the Aztec RPC Server, we don't need to register it as a recipient because we already have the public key available. -> At this point the Sandbox only enables the emitting of encrypted note preimages through encrypted events. -> In the future we will allow emitting arbitrary information. -> (If you currently emit arbitrary information, Aztec RPC Server will fail to decrypt, process and store this data, so it will not be queryable). +At this point the Sandbox only enables the emitting of encrypted note preimages through encrypted events. +In the future we will allow emitting arbitrary information. +(If you currently emit arbitrary information, Aztec RPC Server will fail to decrypt, process and store this data, so it will not be queryable). +::: -To emit encrypted logs first import the `emit_encrypted_log` utility function inside your contract: +To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an oracle: #include_code encrypted_import /yarn-project/aztec-nr/value-note/src/utils.nr rust @@ -65,15 +69,33 @@ Then you can call the function: #include_code encrypted /yarn-project/aztec-nr/value-note/src/utils.nr rust -### Unencrypted Events +### Processing Encrypted Events -Unencrypted events are events which can be read by anyone. -They can be emitted by both public and private functions. +One function of Aztec RPC Server is constantly loading encrypted logs from AztecNode and trying to decrypt them. +When new encrypted logs are obtained, the Aztec RPC Server will try to decrypt them using the private encryption key of all the accounts registered inside Aztec RPC Server. +If the decryption is successful, the Aztec RPC Server will store the decrypted note inside a database. +If the decryption fails, the specific log will be discarded. + +For the Aztec RPC Server to successfully process the decrypted note we need to compute the note's 'note hash' and 'nullifier'. +Aztec.nr enables smart contract developers to design custom notes, meaning developers can also customize how a note's note hash and nullifier should be computed. Because of this customizability, and because there will be a potentially-unlimited number of smart contracts deployed to Aztec, an Aztec RPC Server needs to be 'taught' how to compute the custom note hashes and nullifiers for a particular contract. Therefore, developers will need to implement a `compute_note_hash_and_nullifier` function inside their contracts. :::danger +If your function has private state variables, you **MUST** include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events. +::: + +Every time a new note is successfully decrypted, the Aztec RPC Server will expect the existence of a `compute_note_hash_and_nullifier` function, which must teach it how to correctly process the new note. -Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable. +#include_code compute_note_hash_and_nullifier /yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust + +## Unencrypted Events + +Unencrypted events are events which can be read by anyone. +They can be emitted by both public and private functions. + +:::danger +- Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable. +- Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](./functions.md#a-few-useful-inbuilt-oracles). ::: To emit unencrypted logs first import the `emit_unencrypted_log` utility function inside your contract: @@ -104,31 +126,11 @@ aztec-cli get-logs --from 5 --limit 1 All event data is pushed to Ethereum as calldata by the sequencer and for this reason the cost of emitting an event is non-trivial. -> Note: the cost of submitting calldata to Ethereum is currently 4 gas per byte. Currently, in the Sandbox, an encypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. -> A `ValueNote`, for example, currently uses 3 fields elements (plus the fixed overhead of 4). That's roughly `7 * 32 = 224` bytes of information, costing roughly 896 gas. - -> There are plans to compress encrypted note data further. -> There are plans to adopt EIP-4844 blobs to reduce the cost of data submission further. - -## Processing events - -Both the encrypted and unencrypted events are stored in AztecNode. -Unencrypted logs can be queried by anyone as we described above in the [Unencrypted Events](#unencrypted-events) section. - -Encrypted logs need to first be decrypted: - -### Decrypting - -One function of Aztec RPC Server is constantly loading encrypted logs from AztecNode and trying to decrypt them. -When new encrypted logs are obtained, the Aztec RPC Server will try to decrypt them using the private encryption key of all the accounts registered inside Aztec RPC Server. -If the decryption is successful, the Aztec RPC Server will store the decrypted note inside a database. -If the decryption fails, the specific log will be discarded. - -For the Aztec RPC Server to successfully process the decrypted note we need to compute the note's 'note hash' and 'nullifier'. -Aztec.nr enables smart contract developers to design custom notes, meaning developers can also customise how a note's note hash and nullifier should be computed. Because of this customisability, and because there will be a potentially-unlimited number of smart contracts deployed to Aztec, an Aztec RPC Server needs to be 'taught' how to compute the custom note hashes and nullifiers for a particular contract. Therefore, developers will need to implement a `compute_note_hash_and_nullifier` function inside their contracts. - -Every time a new note is successfully decrypted, the Aztec RPC Server will expect the existence of a `compute_note_hash_and_nullifier` function, which must teach it how to correctly process the new note. +:::info +the cost of submitting calldata to Ethereum is currently 4 gas per byte. Currently, in the Sandbox, an encrypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. -This is an example implementation inside the `PrivateTokenContract`: +A `ValueNote`, for example, currently uses 3 fields elements (plus the fixed overhead of 4). That's roughly `7 * 32 = 224` bytes of information. -#include_code compute_note_hash_and_nullifier /yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr rust +- There are plans to compress encrypted note data further. +- There are plans to adopt EIP-4844 blobs to reduce the cost of data submission further. +::: \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/syntax/functions.md b/docs/docs/dev_docs/contracts/syntax/functions.md index 9c8e1b24e00..7e2ee19506b 100644 --- a/docs/docs/dev_docs/contracts/syntax/functions.md +++ b/docs/docs/dev_docs/contracts/syntax/functions.md @@ -102,6 +102,7 @@ Oracles introduce **non-determinism** into a circuit, and thus are `unconstraine - [`auth_witness`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/oracle/auth_witness.nr) - Provides a way to fetch the authentication witness for a given address. This is useful when building account contracts to support approve-like functionality. - [`get_l1_to_l2_message`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/oracle/get_l1_to_l2_message.nr) - Useful for application that receive messages from L1 to be consumed on L2, such as token bridges or other cross-chain applications. - [`notes`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/oracle/notes.nr) - Provides a lot of functions related to notes, such as fetches notes from storage etc, used behind the scenes for value notes and other pre-build note implementations. +- [`logs`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/oracle/logs.nr) - Provides the to log encrypted and unencrypted data. --- diff --git a/docs/docs/dev_docs/contracts/syntax/globals.md b/docs/docs/dev_docs/contracts/syntax/globals.md index 39dc32abdff..1a50ac54066 100644 --- a/docs/docs/dev_docs/contracts/syntax/globals.md +++ b/docs/docs/dev_docs/contracts/syntax/globals.md @@ -47,6 +47,6 @@ context.block_number(); ``` :::info *Why do the available global variables differ per execution environment?* -> The global variables are constrained by the proving environment. In the case of public functions, they are executed on a sequencer that will know the timestamp and number of the next block ( as they are the block producer ). -> In the case of private functions, we cannot be sure which block our transaction will be included in, hence we can not guarantee values for the timestamp or block number. +The global variables are constrained by the proving environment. In the case of public functions, they are executed on a sequencer that will know the timestamp and number of the next block ( as they are the block producer ). +In the case of private functions, we cannot be sure which block our transaction will be included in, hence we can not guarantee values for the timestamp or block number. ::: \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/syntax/main.md b/docs/docs/dev_docs/contracts/syntax/main.md index 870466e98de..c47a2879cc9 100644 --- a/docs/docs/dev_docs/contracts/syntax/main.md +++ b/docs/docs/dev_docs/contracts/syntax/main.md @@ -11,10 +11,10 @@ Aztec.nr contains abstractions which remove the need to understand the low-level - Public and private [state variable types](./state_variables.md) - Some pre-designed notes - Functions for [emitting](../events.md) encrypted and unencrypted logs -- [Oracle functions](./functions.md#oracle-calls) for accessing: +- [Oracle functions](./functions.md#oracle-functions) for accessing: - private state - secrets -- Functions for communicating with Ethereum L1 +- Functions for communicating with [Ethereum L1](./messaging.md) To import Aztec.nr into your Aztec contract project, simply include it as a dependency. For example: diff --git a/docs/docs/dev_docs/contracts/syntax/storage.md b/docs/docs/dev_docs/contracts/syntax/storage.md index e809aa1faf7..2e7019daeba 100644 --- a/docs/docs/dev_docs/contracts/syntax/storage.md +++ b/docs/docs/dev_docs/contracts/syntax/storage.md @@ -7,6 +7,10 @@ An example of such a struct could be as follow: #include_code storage-struct-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust +:::info +If your storage include private state variables it must include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events, see [encrypted events](./../events.md#processing-encrypted-events) for more. +::: + In here, we are setting up a mix of public and private state variables. The public state variables can be read by anyone, and functions manipulating them are executed by the sequence, we will see more to this in [functions](./functions.md#public-functions) in a few moments. The private state variables are only readable by their owner, or people whom the owner have shared the data with. As mentioned earlier in the foundational concepts ([state model](./../../../concepts/foundation/state_model.md) and [private/public execution](./../../../concepts/foundation/communication/public_private_calls.md)) private state are following a UTXO model where only the people knowing the pre-images of the commitments in the state will be able to use that knowledge. diff --git a/docs/sidebars.js b/docs/sidebars.js index 84995d845b5..099c6b0a230 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -211,10 +211,6 @@ const sidebars = { items: [ "dev_docs/contracts/workflow", "dev_docs/contracts/layout", - "dev_docs/contracts/events", - "dev_docs/contracts/compiling", - "dev_docs/contracts/deploying", - "dev_docs/contracts/artifacts", { label: "Syntax", type: "category", @@ -223,9 +219,9 @@ const sidebars = { id: "dev_docs/contracts/syntax/main", }, items: [ - "dev_docs/contracts/syntax/contract", "dev_docs/contracts/syntax/storage", "dev_docs/contracts/syntax/state_variables", + "dev_docs/contracts/syntax/events", "dev_docs/contracts/syntax/functions", "dev_docs/contracts/syntax/context", "dev_docs/contracts/syntax/globals", @@ -246,6 +242,9 @@ const sidebars = { "dev_docs/contracts/portals/outbox", ], }, + "dev_docs/contracts/compiling", + "dev_docs/contracts/deploying", + "dev_docs/contracts/artifacts", // { // label: "Resources", // type: "category", diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr index 6105bb8f675..9fc38917054 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr @@ -419,6 +419,7 @@ contract Token { // Below this point is the stuff of nightmares. // This should ideally not be required. What do we do if vastly different types of preimages? + // docs:start:compute_note_hash_and_nullifier // Computes note hash and nullifier. // Note 1: Needs to be defined by every contract producing logs. // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. @@ -430,6 +431,7 @@ contract Token { note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) } } + // docs:end:compute_note_hash_and_nullifier } // docs:end:token_all From ae55ad45a349f6862136283a7856f7f688b714b3 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 19 Sep 2023 22:06:52 +0000 Subject: [PATCH 3/7] chore: fix broken links --- docs/docs/dev_docs/contracts/syntax/main.md | 2 +- docs/docs/dev_docs/contracts/syntax/state_variables.md | 2 +- docs/docs/dev_docs/contracts/syntax/storage.md | 2 +- docs/docs/dev_docs/dapps/tutorials/contract_interaction.md | 2 +- docs/docs/dev_docs/testing/testing.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/dev_docs/contracts/syntax/main.md b/docs/docs/dev_docs/contracts/syntax/main.md index c47a2879cc9..7dfa37376c7 100644 --- a/docs/docs/dev_docs/contracts/syntax/main.md +++ b/docs/docs/dev_docs/contracts/syntax/main.md @@ -10,7 +10,7 @@ Aztec.nr contains abstractions which remove the need to understand the low-level - Public and private [state variable types](./state_variables.md) - Some pre-designed notes -- Functions for [emitting](../events.md) encrypted and unencrypted logs +- Functions for [emitting](./events.md) encrypted and unencrypted logs - [Oracle functions](./functions.md#oracle-functions) for accessing: - private state - secrets diff --git a/docs/docs/dev_docs/contracts/syntax/state_variables.md b/docs/docs/dev_docs/contracts/syntax/state_variables.md index 517671de8a5..c9868cc47bf 100644 --- a/docs/docs/dev_docs/contracts/syntax/state_variables.md +++ b/docs/docs/dev_docs/contracts/syntax/state_variables.md @@ -92,7 +92,7 @@ For example, the following function calls the account contract before it updates In contrast to public state, private state is persistent state that is _not_ visible to the whole world. Depending on the logic of the smart contract, a _private_ state variable's current value will only be known to one entity, or a closed group of entities. -The value of a private state variable can either be shared via [events](../events), or offchain via web2, or completely offline: it's up to the app developer. +The value of a private state variable can either be shared via [events](./events.md), or offchain via web2, or completely offline: it's up to the app developer. Aztec private state follows a utxo-based model. That is, a private state's current value is represented as one or many [notes](#notes). Each note is stored as an individual leaf in a utxo-based merkle tree: the [private state tree](/concepts/advanced/data_structures/trees#private-state-tree). diff --git a/docs/docs/dev_docs/contracts/syntax/storage.md b/docs/docs/dev_docs/contracts/syntax/storage.md index 2e7019daeba..3d5c06c9169 100644 --- a/docs/docs/dev_docs/contracts/syntax/storage.md +++ b/docs/docs/dev_docs/contracts/syntax/storage.md @@ -8,7 +8,7 @@ An example of such a struct could be as follow: #include_code storage-struct-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust :::info -If your storage include private state variables it must include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events, see [encrypted events](./../events.md#processing-encrypted-events) for more. +If your storage include private state variables it must include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events, see [encrypted events](./events.md#processing-encrypted-events) for more. ::: In here, we are setting up a mix of public and private state variables. The public state variables can be read by anyone, and functions manipulating them are executed by the sequence, we will see more to this in [functions](./functions.md#public-functions) in a few moments. The private state variables are only readable by their owner, or people whom the owner have shared the data with. diff --git a/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md b/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md index bf029bdea39..545cc827100 100644 --- a/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md +++ b/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md @@ -121,7 +121,7 @@ Balance of 0x226f8087792beff8d5009eb94e65d2a4a505b70baf4a9f28d33c8d620b0ba972: 0 Balance of 0x0e1f60e8566e2c6d32378bdcadb7c63696e853281be798c107266b8c3a88ea9b: 0 ``` -Public functions can emit [unencrypted public logs](../../contracts/events.md#unencrypted-events), which we can query via the RPC Server interface. For example, here we have a `mint` method that emits a generic `Coins minted` whenever it is called: +Public functions can emit [unencrypted public logs](../../contracts/syntax/events.md#unencrypted-events), which we can query via the RPC Server interface. In particular, the public token contract emits a generic `Coins minted` whenever the `mint` method is called: #include_code unencrypted_log yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr rust diff --git a/docs/docs/dev_docs/testing/testing.md b/docs/docs/dev_docs/testing/testing.md index ef2ce16123a..d8bdf31adbe 100644 --- a/docs/docs/dev_docs/testing/testing.md +++ b/docs/docs/dev_docs/testing/testing.md @@ -149,7 +149,7 @@ We can query the RPC server for all notes encrypted for a given user in a contra ### Logs -Last but not least, we can check the logs of [events](../contracts/events.md) emitted by our contracts. Contracts in Aztec can emit both [encrypted](../contracts/events.md#encrypted-events) and [unencrypted](../contracts/events.md#unencrypted-events) events. +Last but not least, we can check the logs of [events](../contracts/syntax/events.md) emitted by our contracts. Contracts in Aztec can emit both [encrypted](../contracts/syntax/events.md#encrypted-events) and [unencrypted](../contracts/syntax/events.md#unencrypted-events) events. :::info At the time of this writing, only unencrypted events can be queried directly. Encrypted events are always assumed to be encrypted notes. From 9a031e947d7f7783017dc9c4f4bc66d567e2e45a Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 20 Sep 2023 07:09:26 +0000 Subject: [PATCH 4/7] chore: address maddia comments --- docs/docs/dev_docs/contracts/aztec_types.md | 8 +++++--- docs/docs/dev_docs/contracts/layout.md | 4 ++-- docs/docs/dev_docs/contracts/syntax/events.md | 6 +++--- .../dev_docs/contracts/syntax/functions.md | 2 +- docs/docs/dev_docs/contracts/syntax/storage.md | 18 +++++++++--------- docs/docs/dev_docs/limitations/main.md | 14 +++++++------- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/docs/docs/dev_docs/contracts/aztec_types.md b/docs/docs/dev_docs/contracts/aztec_types.md index ca73d7ab5b2..53561364f19 100644 --- a/docs/docs/dev_docs/contracts/aztec_types.md +++ b/docs/docs/dev_docs/contracts/aztec_types.md @@ -3,13 +3,15 @@ title: Aztec.nr Types description: Documentation of Aztec's Types --- -With Aztec.nr we are include a series of types that are useful for writing Aztec contracts. While almost anything is modelled just as plain Fields underneath it can be quite useful for developers to have a series of types when writing that apply different types of constrains on top to make the code more readable and easier to follow. +With Aztec.nr we include a series of useful types. While most types are Fields underneath it can be useful for developers to have custom types that: +1. Apply different types of constrains +2. Make the code easier to follow -## `AztecAddress` +A Field wrapper that alters the name. Making it explicit that the value is an address, and not something else. A wrapper around a Field that mainly just alters the name to make it more clear that the value is an address and not a number of a hash or something else. -## `EthereumAddress` +A wrapper around a Field that performs a range check to ensure that the value is 20 bytes. A wrapper around a Field that perform a range check to ensure that the number of bytes used don't exceed 20. diff --git a/docs/docs/dev_docs/contracts/layout.md b/docs/docs/dev_docs/contracts/layout.md index 2e6420cf75d..50832159f1a 100644 --- a/docs/docs/dev_docs/contracts/layout.md +++ b/docs/docs/dev_docs/contracts/layout.md @@ -2,7 +2,7 @@ title: Structure --- -A contract is a collection of persistent [state variables](./syntax/state_variables.md), and [functions](./syntax/functions) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. +A contract is a collection of persistent [state variables](./syntax/state_variables.md), and [functions](./syntax/functions) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of the other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. # Contract @@ -20,7 +20,7 @@ contract MyContract { } ``` :::info A note for vanilla Noir devs -There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). +There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir `contract` scope. More than one function can be an entrypoint. ::: ## Directory structure diff --git a/docs/docs/dev_docs/contracts/syntax/events.md b/docs/docs/dev_docs/contracts/syntax/events.md index 2c47231e139..f09a4aa66d4 100644 --- a/docs/docs/dev_docs/contracts/syntax/events.md +++ b/docs/docs/dev_docs/contracts/syntax/events.md @@ -61,7 +61,7 @@ In the future we will allow emitting arbitrary information. (If you currently emit arbitrary information, Aztec RPC Server will fail to decrypt, process and store this data, so it will not be queryable). ::: -To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an oracle: +To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an [oracle](./functions.md#oracle-functions): #include_code encrypted_import /yarn-project/aztec-nr/value-note/src/utils.nr rust @@ -71,7 +71,7 @@ Then you can call the function: ### Processing Encrypted Events -One function of Aztec RPC Server is constantly loading encrypted logs from AztecNode and trying to decrypt them. +One function of Aztec RPC Server is constantly loading encrypted logs from an AztecNode and decrypting them. When new encrypted logs are obtained, the Aztec RPC Server will try to decrypt them using the private encryption key of all the accounts registered inside Aztec RPC Server. If the decryption is successful, the Aztec RPC Server will store the decrypted note inside a database. If the decryption fails, the specific log will be discarded. @@ -127,7 +127,7 @@ aztec-cli get-logs --from 5 --limit 1 All event data is pushed to Ethereum as calldata by the sequencer and for this reason the cost of emitting an event is non-trivial. :::info -the cost of submitting calldata to Ethereum is currently 4 gas per byte. Currently, in the Sandbox, an encrypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. +The cost of submitting calldata to Ethereum is currently 4 gas per byte. In the Sandbox, an encrypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. A `ValueNote`, for example, currently uses 3 fields elements (plus the fixed overhead of 4). That's roughly `7 * 32 = 224` bytes of information. diff --git a/docs/docs/dev_docs/contracts/syntax/functions.md b/docs/docs/dev_docs/contracts/syntax/functions.md index 7e2ee19506b..e1a01f03dd0 100644 --- a/docs/docs/dev_docs/contracts/syntax/functions.md +++ b/docs/docs/dev_docs/contracts/syntax/functions.md @@ -1,6 +1,6 @@ --- title: Functions -description: This page will go over functions, how private and public functions differ and how then can be used together. +description: This page covers functions, private and public functions composability, as well as their differences. --- diff --git a/docs/docs/dev_docs/contracts/syntax/storage.md b/docs/docs/dev_docs/contracts/syntax/storage.md index 3d5c06c9169..9b04e3efecc 100644 --- a/docs/docs/dev_docs/contracts/syntax/storage.md +++ b/docs/docs/dev_docs/contracts/syntax/storage.md @@ -3,35 +3,35 @@ In an Aztec.nr contract, storage is to be defined as a single struct. (This enables us to declare types composed of nested generics in Noir). The struct **must** be called `Storage` for the Aztec.nr library to properly handle it (will be fixed in the future to support more flexibility). -An example of such a struct could be as follow: +An example of such a struct could be as follows: #include_code storage-struct-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust :::info -If your storage include private state variables it must include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events, see [encrypted events](./events.md#processing-encrypted-events) for more. +If your storage includes private state variables it must include a `compute_note_hash_and_nullifier` function to allow the RPC to process encrypted events, see [encrypted events](./events.md#processing-encrypted-events) for more. ::: -In here, we are setting up a mix of public and private state variables. The public state variables can be read by anyone, and functions manipulating them are executed by the sequence, we will see more to this in [functions](./functions.md#public-functions) in a few moments. The private state variables are only readable by their owner, or people whom the owner have shared the data with. +In the storage stuct, we set up a mixture of public and private state variables. The public state variables can be read by anyone, and functions manipulating them are executed by the sequencer, (see [functions](./functions.md#public-functions)). Private state variables are only readable by their owner, or people whom the owner has shared the data with. -As mentioned earlier in the foundational concepts ([state model](./../../../concepts/foundation/state_model.md) and [private/public execution](./../../../concepts/foundation/communication/public_private_calls.md)) private state are following a UTXO model where only the people knowing the pre-images of the commitments in the state will be able to use that knowledge. +As mentioned earlier in the foundational concepts ([state model](./../../../concepts/foundation/state_model.md) and [private/public execution](./../../../concepts/foundation/communication/public_private_calls.md)) private state follows a UTXO model. Where note pre-images are only known to those able to decrypt them. -It is currently required to specify the length of the types when declaring the storage struct. The length will depend on the type of the state variable you are using with the length being the number of Field elements used to represent it. +It is currently required to specify the length of the types when declaring the storage struct. If your type is a struct, this will be the number of values in your struct ( with arrays flattened ). -Since Aztec.nr is a library on top of Noir, we can use the types defined in Noir, so it can be useful to consult the [Noir documentation](https://noir-lang.org/language_concepts/data_types) for information on types. +Since Aztec.nr is a library written in Noir, we can use the types defined in Noir, so it can be useful to consult the [Noir documentation](https://noir-lang.org/language_concepts/data_types) for information on types. -Currently, the sandbox also require that you specify how this storage struct is going to be initialized. Initialized here being how the state variables should be "setup" such that they can be read properly by the contract. This is done by specifying an `init` function that is run in functions that rely on reading or altering the state variables. +Currently, the sandbox also requires that you specify how this storage struct is "initialized". This is done by specifying an `init` function that is run in functions that rely on reading or altering the state variables. An example of such a function for the above storage struct would be: #include_code storage-declaration /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust :::warning Using slot `0` is not supported! -No storage values should be initialized at slot `0`. If you are using slot `0` for storage, you will not get an error when compiling, but the contract will not be updating the storage! This is a known bug that will be fixed in the future. +No storage values should be initialized at slot `0`. If you are using slot `0` for storage, you will not get an error when compiling, but the contract will not be updating the storage! This is a known issue that will be fixed in the future. ::: In [State Variables](./state_variables.md) we will see in more detail what each of these types are, how they work and how to initialize them. -To use the storage in functions, e.g., functions where you would read or write storage, you need to initialize the struct first, and then you can read and write afterwards. +To use storage in functions, e.g., functions where you would read or write storage, you need to initialize the struct first, and then you can read and write afterwards. #include_code storage-init /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust diff --git a/docs/docs/dev_docs/limitations/main.md b/docs/docs/dev_docs/limitations/main.md index 4b54fd87ea9..4a5200c2de1 100644 --- a/docs/docs/dev_docs/limitations/main.md +++ b/docs/docs/dev_docs/limitations/main.md @@ -26,14 +26,14 @@ Help shape and define: - Educational content; - Core protocol improvements; -## Limitations that devs need to know about -- It is a testing environment, it is insecure, unaudited and don't generate any proofs, its only for testing purposes; -- Constructor can't call or alter public state - - the constructor is completely executed in private domain, WITHOUT the ability to call public functions or alter public state. This means that to set initial storage values, you need to follow a pattern similar to proxies in Eth, where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions.md#constructor). -- No static or delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). - - there are values in the call-context, but they are not used. Beware that what you think of as a `view` could alter state ATM! Notable the account could alter state or re-enter whenever the account `is_valid` is called. +## Limitations developers need to know about +- It is a testing environment, it is insecure, unaudited and does not generate any proofs, its only for testing purposes; +- Constructors can not call nor alter public state + - The constructor is executed exclusively in private domain, WITHOUT the ability to call public functions or alter public state. This means to set initial storage values, you need to follow a pattern similar to [proxies in Ethereum](https://blog.openzeppelin.com/proxy-patterns), where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions.md#constructor). +- No static nor delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). + - There are unused values in the call-context. Beware that what you think of as a `view` could alter state ATM! Notably the account could alter state or re-enter whenever the account contract's `is_valid` function is called. - `msg_sender` is leaked when doing private -> public calls - - the `msg_sender` will always be set, so if you call a public function from the private world, the `msg_sender` will be set to the private caller's address 😱, see [function context](../contracts/syntax/context.mdx). + - The `msg_sender` will always be set, if you call a public function from the private world, the `msg_sender` will be set to the private caller's address. See [function context](../contracts/syntax/context.mdx). - The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions.md#function-visibility). - Unencrypted logs don't link to the contract that emitted it, so essentially just a `debug_log`` that you can match values against. - A note that is created and nullified in the same transaction will still emit an encrypted log. From 046cab3fec7b6250802768efeb109edab078932c Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 20 Sep 2023 11:32:04 +0000 Subject: [PATCH 5/7] chore: address rahul comments --- docs/docs/dev_docs/contracts/syntax/events.md | 12 ++++++------ docs/docs/dev_docs/limitations/main.md | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/docs/dev_docs/contracts/syntax/events.md b/docs/docs/dev_docs/contracts/syntax/events.md index f09a4aa66d4..c50526530f0 100644 --- a/docs/docs/dev_docs/contracts/syntax/events.md +++ b/docs/docs/dev_docs/contracts/syntax/events.md @@ -54,7 +54,7 @@ await aztecRpc.registerRecipient(completeAddress); :::info -If a note recipient is one of the accounts inside the Aztec RPC Server, we don't need to register it as a recipient because we already have the public key available. +If a note recipient is one of the accounts inside the Aztec RPC Server, we don't need to register it as a recipient because we already have the public key available. You can register a recipient as shown [here](../deploying#deploying-private-token-contract) At this point the Sandbox only enables the emitting of encrypted note preimages through encrypted events. In the future we will allow emitting arbitrary information. @@ -71,7 +71,7 @@ Then you can call the function: ### Processing Encrypted Events -One function of Aztec RPC Server is constantly loading encrypted logs from an AztecNode and decrypting them. +One of the functions of the Aztec RPC Server is constantly loading encrypted logs from the `AztecNode` and decrypting them. When new encrypted logs are obtained, the Aztec RPC Server will try to decrypt them using the private encryption key of all the accounts registered inside Aztec RPC Server. If the decryption is successful, the Aztec RPC Server will store the decrypted note inside a database. If the decryption fails, the specific log will be discarded. @@ -126,11 +126,11 @@ aztec-cli get-logs --from 5 --limit 1 All event data is pushed to Ethereum as calldata by the sequencer and for this reason the cost of emitting an event is non-trivial. -:::info -The cost of submitting calldata to Ethereum is currently 4 gas per byte. In the Sandbox, an encrypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. +In the Sandbox, an encrypted note has a fixed overhead of 4 field elements (to broadcast an ephemeral public key, a contract address, and a storage slot); plus a variable number of field elements depending on the type of note being emitted. A `ValueNote`, for example, currently uses 3 fields elements (plus the fixed overhead of 4). That's roughly `7 * 32 = 224` bytes of information. +#include_code value-note-def /yarn-project/aztec-nr/value-note/src/value_note.nr + - There are plans to compress encrypted note data further. -- There are plans to adopt EIP-4844 blobs to reduce the cost of data submission further. -::: \ No newline at end of file +- There are plans to adopt EIP-4844 blobs to reduce the cost of data submission further. \ No newline at end of file diff --git a/docs/docs/dev_docs/limitations/main.md b/docs/docs/dev_docs/limitations/main.md index 4a5200c2de1..3b8ae640cc3 100644 --- a/docs/docs/dev_docs/limitations/main.md +++ b/docs/docs/dev_docs/limitations/main.md @@ -31,7 +31,8 @@ Help shape and define: - Constructors can not call nor alter public state - The constructor is executed exclusively in private domain, WITHOUT the ability to call public functions or alter public state. This means to set initial storage values, you need to follow a pattern similar to [proxies in Ethereum](https://blog.openzeppelin.com/proxy-patterns), where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions.md#constructor). - No static nor delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). - - There are unused values in the call-context. Beware that what you think of as a `view` could alter state ATM! Notably the account could alter state or re-enter whenever the account contract's `is_valid` function is called. + - These values are unused in the call-context. + - Beware that what you think of as a `view` could alter state ATM! Notably the account could alter state or re-enter whenever the account contract's `is_valid` function is called. - `msg_sender` is leaked when doing private -> public calls - The `msg_sender` will always be set, if you call a public function from the private world, the `msg_sender` will be set to the private caller's address. See [function context](../contracts/syntax/context.mdx). - The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions.md#function-visibility). From e7148828cb4b47745b06a9c91b273f1c4b4f89df Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 20 Sep 2023 11:59:25 +0000 Subject: [PATCH 6/7] chore: rebase fixes --- docs/docs/dev_docs/limitations/main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev_docs/limitations/main.md b/docs/docs/dev_docs/limitations/main.md index 3b8ae640cc3..d55bb375404 100644 --- a/docs/docs/dev_docs/limitations/main.md +++ b/docs/docs/dev_docs/limitations/main.md @@ -33,7 +33,7 @@ Help shape and define: - No static nor delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). - These values are unused in the call-context. - Beware that what you think of as a `view` could alter state ATM! Notably the account could alter state or re-enter whenever the account contract's `is_valid` function is called. -- `msg_sender` is leaked when doing private -> public calls +- `msg_sender` is currently leaking when doing private -> public calls - The `msg_sender` will always be set, if you call a public function from the private world, the `msg_sender` will be set to the private caller's address. See [function context](../contracts/syntax/context.mdx). - The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions.md#function-visibility). - Unencrypted logs don't link to the contract that emitted it, so essentially just a `debug_log`` that you can match values against. From 264a4e034875d2eb249895ac6643511e22198210 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 20 Sep 2023 12:22:05 +0000 Subject: [PATCH 7/7] chore: rm aztec_types.md --- docs/docs/dev_docs/contracts/aztec_types.md | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 docs/docs/dev_docs/contracts/aztec_types.md diff --git a/docs/docs/dev_docs/contracts/aztec_types.md b/docs/docs/dev_docs/contracts/aztec_types.md deleted file mode 100644 index 53561364f19..00000000000 --- a/docs/docs/dev_docs/contracts/aztec_types.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Aztec.nr Types -description: Documentation of Aztec's Types ---- - -With Aztec.nr we include a series of useful types. While most types are Fields underneath it can be useful for developers to have custom types that: -1. Apply different types of constrains -2. Make the code easier to follow - -A Field wrapper that alters the name. Making it explicit that the value is an address, and not something else. - -A wrapper around a Field that mainly just alters the name to make it more clear that the value is an address and not a number of a hash or something else. - -A wrapper around a Field that performs a range check to ensure that the value is 20 bytes. - -A wrapper around a Field that perform a range check to ensure that the number of bytes used don't exceed 20. - -