Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): Document slow update tree #3416

Merged
merged 28 commits into from
Dec 1, 2023
Merged
Changes from 17 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f366378
slow update tree explanation
catmcgee Nov 24, 2023
412b298
sidebar
catmcgee Nov 24, 2023
b7f91fb
how-to without include_code
catmcgee Nov 24, 2023
a477e0a
delete file
catmcgee Nov 24, 2023
777dc54
sidebar
catmcgee Nov 24, 2023
e1fef5a
docs build errors
catmcgee Nov 25, 2023
6dec84f
include_code
catmcgee Nov 26, 2023
05f4049
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 26, 2023
fd14bf2
fix typo
catmcgee Nov 26, 2023
43d687c
fix docs build errors
catmcgee Nov 26, 2023
cc5be40
Merge branch 'master' into docs-slow-updates-tree
critesjosh Nov 27, 2023
f9d37e3
Apply suggestions from code review
catmcgee Nov 28, 2023
7b22f94
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 28, 2023
7e2560f
address changes, added reference
catmcgee Nov 28, 2023
5c8a915
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 28, 2023
1db9550
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 28, 2023
84d7488
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 28, 2023
46cbad0
more information on each component, restructured, diagram
catmcgee Nov 29, 2023
4a66e8c
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 29, 2023
9f96bb2
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 29, 2023
d509627
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 29, 2023
08d0030
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 30, 2023
e6a95f5
historic -> historical
catmcgee Nov 30, 2023
33a0a8a
Merge branch 'master' into docs-slow-updates-tree
catmcgee Nov 30, 2023
d3c98c1
comments & grammar
catmcgee Dec 1, 2023
2f3e733
broken link
catmcgee Dec 1, 2023
78cd724
merge conflicts
catmcgee Dec 1, 2023
21b814d
Merge branch 'master' into docs-slow-updates-tree
catmcgee Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/concepts/foundation/communication/main.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@ title: Contract Communication

This section will walk over communication types that behaves differently than normal function calls from.

Namely, if functions are in different domains, private vs. public, their execution behaves a little differently to what you might expect! See [Private <--> Public execution](./public_private_calls.md).
Namely, if functions are in different domains, private vs. public, their execution behaves a little differently to what you might expect! See [Private <--> Public execution](./public_private_calls/main.md).

Likewise, executing a function on a different domain than its origin needs a bit extra thought. See [L1 <--> L2 communication](./cross_chain_calls.md).
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ title: Private <--> Public execution

import Image from "@theme/IdealImage";

import Disclaimer from "../../../misc/common/\_disclaimer.mdx";
import Disclaimer from "../../../../misc/common/\_disclaimer.mdx";
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

<Disclaimer/>

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: Privately access Historic Public Data
---

In Aztec, private and public execution environments are completely separate and operate with distinct state management. It is not possible for private functions to reliably access the most recent public data public state - only sequencers can do that.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

But, what about historical public data (or public data that changes infrequently)? Through a **slow updates tree**, private functions can access historical public state. Please note that we are still experimenting with this feature.

On this page you will learn:

1. Why a slow updates tree exists & use cases
2. How it works
3. How it can be used to access historical public data
4. Limitations

## The need for a slow updates tree
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

This structure was created specifically to privately & publicly access historical public data that is not updated often. It should be used to store data that is not sensitive but needs to be accessible from private smart contracts. Using a slow updates tree, it is possible to:
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

- Access historic public data from a private function
- Access historic public data from a public function
- Update public data (that does not need updated often) from public and private functions

This data structure is ideal for these use cases:

- Address Registry: Enabling contracts to interact with other contracts more easily requires address storage accessible in both public and private executions. This can be particularly helpful in things such as proxy contracts.
- Access Control: Managing privileges in contracts, such as a token contract owner’s ability to mint new tokens, is streamlined when control information is shared between public and private executions. This might include things like blacklists and whitelists.

## How it works

We developed the Slow Update Tree to help balance public and private execution in a blockchain context.

Earlier systems typically used either fully public or entirely private state trees, which led to privacy leaks if reading public data from private state.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

Using a shared state tree, it is possible to privately access historic public data by providing a membership proof to show that a value is indeed part of a commitment, and then check that the commitment matches the one stored in the state, as shown below.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

```mermaid
graph TD;
Cm[CommitmentToKnowingAValue] --> Vm1[Value1]
Cm --> Vm2[Value2]
Cm --> Vmn[Value3]
Vm1 --> Mp1[Membership Proof for Value1]
Mp1 --> St[Commitment in State]
St --> Cm
```

However this means that any changes to the commitment will invalidate our membership proof, and make our read fail.

To solve this, the Slow Update Tree is a dual-tree structure - using a current and pending tree - that updates at the end of an epoch. This way, we can ensure that the values are stable throughout the epoch, and that the membership proofs are not invalidated by changes in other contracts more than once every epoch.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

```mermaid
graph TD;
Change{Epoch Over} -->|True| Current{Current}
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
Change -->|False| Pending{Pending}
Current --> Current1[Current Commitment 1]
Current --> CurrentM[Current Commitment 2]
CurrentM --> Value1[Current Value 1]
CurrentM --> Value2[Current Value 2]
CurrentM --> ValueN[Current Value n]
Pending --> PendingM[Pending Commitment 1]
PendingM --> PValue1[Pending Value 1]
PendingM --> PValue2[Pending Value 2]
PendingM --> PValueN[Pending Value n]
```

### Dual Tree Structure
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

The Slow Update Tree operates on a dual-tree mechanism - a _current_ tree and a _pending_ tree. These trees manage the state data that needs to be shared between public and private executions.

This _slow update_ mechanism minimizes the invalidation of reads and writes due to concurrent updates.

### Epoch-Based Updates

The current tree is replaced with the pending tree at the end of each epoch. Then a new pending tree is created, the epoch restarts, and the cycle begins again.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

### Accessing Data

**From public state:** Accessed directly from the state
**From private state:** Performs a membership proof for the values in the tree, ensuring that they are part of the commitment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again why commitment? In Aztec, commitment was so confusing for everyone that we moved away to notes and note hashes. Let's not reintroduce it. It is simply a tree


catmcgee marked this conversation as resolved.
Show resolved Hide resolved
### Updating Values

Updates are made to the pending tree. Then at the end of each epoch, the updates in the pending tree are committed and it becomes the current tree.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

## Limitations

### Delayed State Finality

Updates in the Slow Update Tree are only finalized at the end of an epoch.

This could potentially lead to delays in state changes - for example an address may be added to a blacklist but this will not be reflected in the state until the end of the current epoch.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

### Complexity in State Management

Developers are used to instant state updates, so the Slow Update Tree might take some getting used to. But we believe this won't take long!
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

For a code walkthrough of how a token blacklist contract can use a slow updates tree, read [this](../../../../dev_docs/contracts/syntax/slow_updates_tree.md).
2 changes: 1 addition & 1 deletion docs/docs/concepts/foundation/main.md
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ A user of the Aztec network will interact with the network through Aztec.js. Azt

### Private Execution Environment

The PXE provides a secure environment for the execution of sensitive operations, ensuring private information and decrypted data are not accessible to unauthorized applications. It hides the details of the [state model](./state_model/main.md) from end users, but the state model is important for Aztec developers to understand as it has implications for [private/public execution](./communication/public_private_calls.md) and [L1/L2 communication](./communication/cross_chain_calls.md). The PXE also includes the [ACIR Simulator](../advanced/acir_simulator.md) for private executions and the KeyStore for secure key management.
The PXE provides a secure environment for the execution of sensitive operations, ensuring private information and decrypted data are not accessible to unauthorized applications. It hides the details of the [state model](./state_model/main.md) from end users, but the state model is important for Aztec developers to understand as it has implications for [private/public execution](./communication/public_private_calls/main.md) and [L1/L2 communication](./communication/cross_chain_calls.md). The PXE also includes the [ACIR Simulator](../advanced/acir_simulator.md) for private executions and the KeyStore for secure key management.

Procedurally, the PXE sends results of private function execution and requests for public function executions to the [sequencer](./nodes_clients/sequencer.md), which will update the state of the rollup.

4 changes: 2 additions & 2 deletions docs/docs/dev_docs/contracts/syntax/functions.md
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ In Aztec there are multiple different types of visibility that can be applied to

### Data Visibility

Data visibility is used to describe whether the data (or state) used in a function is generally accessible (public) or on a need to know basis (private). Functions with public data visibility are executed by the sequencer, and functions with private data visibility are executed by the user. For more information on why this is the case, see [communication](../../../concepts/foundation/communication/public_private_calls.md).
Data visibility is used to describe whether the data (or state) used in a function is generally accessible (public) or on a need to know basis (private). Functions with public data visibility are executed by the sequencer, and functions with private data visibility are executed by the user. For more information on why this is the case, see [communication](../../../concepts/foundation/communication/public_private_calls/main.md).

In the following sections, we are going to see how these two "types" co-exists and interact.

@@ -213,7 +213,7 @@ Calling a public function from another public function is quite similar to what

### Private -> Public

As discussed above, private function execution and calls take place on the user's device, while public function execution and calls take place on a sequencer, in two different places at two different times, it is natural to question how we can achieve composability between the two. The solution is asynchronicity. Further reading can be found in the foundational concepts [here](../../../concepts/foundation/communication/public_private_calls.md).
As discussed above, private function execution and calls take place on the user's device, while public function execution and calls take place on a sequencer, in two different places at two different times, it is natural to question how we can achieve composability between the two. The solution is asynchronicity. Further reading can be found in the foundational concepts [here](../../../concepts/foundation/communication/public_private_calls/main.md).

Private function execution takes place on the users device, where it keeps track of any public function calls that have been made. Whenever private execution completes, and a kernel proof is produced, the transaction sent to the network will include all of the public calls that were dispatched.
When the sequencer receives the messages, it will take over and execute the public parts of the transaction.
219 changes: 219 additions & 0 deletions docs/docs/dev_docs/contracts/syntax/slow_updates_tree.md
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
---
title: Slow Updates Tree
---

Slow Updates Tree is a data structure that allows for public data to be accessed in both private and public domains. Read the high level overview in the [concepts section](../../../concepts/foundation/communication/public_private_calls/slow_updates_tree.md).
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

The Slow Updates Tree works by having a current tree and a pending tree, and replacing the current tree with the pending tree after an epoch has passed. Public functions can read directly from the current tree, and private functions can perform a membership proof that values are part of a commitment to the current state of the tree.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

On this page you will learn:

1. About the SlowTree.nr smart contract
2. The components involved in using the Slow Updates Tree
3. How you can integrate it into your own smart contract

Scroll down to view [integration guide](./slow_updates_tree.md#how-to-integrate-a-slow-updates-tree) and [reference](./slow_updates_tree.md#reference).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These links dont go anywhere.


# Exploring an example integration through a **`TokenBlacklist`** Smart Contract
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

The `TokenBlacklist` contract is a token contract that does not allow blacklisted accounts to perform mints or transfers. To achieve this, it interacts with a Slow Updates Tree primarily through the `SlowMap` interface. There are four main components involved in this smart contract:

1. **TokenBlacklist.nr Contract:** This is the primary smart contract that utilizes the Slow Updates Tree for managing blacklisted addresses
2. **SlowMap Interface**: This interface is used within the `TokenBlacklist` contract to interact with the Slow Updates Tree. It provides methods for reading and updating values in the tree in both public and private contexts.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved
3. **SlowTree.nr Contract**: This is a smart contract that instantiates a slow updates tree and allows us to access and manipulate its contents.
4. **SlowMap type**: This is a type in the Azetc library that is utilized by the SlowTree contract.
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

## TokenBlacklist Contract

You can find the full code for the TokenBlacklist smart contract [here](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts/token_blacklist_contract).

### Importing SlowMap

The contract first imports the **`SlowMap`** interface:

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

The **`SlowMap`** interface allows the contract to interact with its attached SlowTree. It abstracts these functions so they do not have to be implemented in the TokenBlacklist contract.

### Constructor and Initialization of the Slow Updates Tree
catmcgee marked this conversation as resolved.
Show resolved Hide resolved

The contract's constructor takes the address of the slow updates contract:

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

This initialization sets up the connection between the **`TokenBlacklist`** contract and a previously deployed SlowTree, allowing it to use the SlowMap interface to directly interact with the SlowTree.

### Private Transfer Function Utilizing the Slow Updates Tree

In the private transfer function, the contract uses the **`SlowMap`** interface to check if a user is blacklisted:

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

Here, the contract reads the roles of the sender and recipient from the SlowTree using the **`read_at`** function in the **`SlowMap`**interface. It checks if either party is blacklisted, and if so, the transaction does not go ahead.

## SlowTree.nr smart contract

Under the hood, this TokenBlacklist contract uses the SlowMap interface to interact with a SlowTree contract. SlowTree.nr is a contract that utilizes the slow update tree library and instansiates and manipulates a tree.

If you are using the SlowTree contract with the SlowMap interface, the exact implementation details of this smart contract are not required to know. You can read the code [here](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts/slow_tree_contract).

## The SlowMap interface

This interface used by the TokenBlackList contract contains multiple functions for interacting with its associated SlowTree. You can find the interface [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/token_blacklist_contract/src/interfaces.nr).

## The SlowMap type

This is a library provided by Aztec for low-level interacts with a slow updates tree. You can see the code for the library [here](https://github.com/AztecProtocol/aztec-nr/blob/master/slow-updates-tree/src/slow_map.nr).


# How to integrate a slow updates tree

You can use this example to implement a slow updates tree in your own smart contract.

1. Copy the SlowTree.nr example and its dependencies, found [here](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts/slow_tree_contract). Replace the constants with whatever you like and deploy it to your sandbox
2. Copy the SlowMap interface for easy interaction with your deployed SlowTree. Find it [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/token_blacklist_contract/src/interfaces.nr)
3. Import the SlowMap interface into your contract

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

5. Store a slow updates tree in both public and private storage

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

6. Store the SlowTree address in private storage as a FieldNote

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

7. Store the SlowTree address in public storage and initialize an instance of SlowMap using this address

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

8. Now you can read and update from private functions:

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

9. Or from public functions:

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

# Reference

## Struct `SlowMap`

### Overview
The `SlowMap` struct is used to interact with a slow updates tree deployed via the SlowTree smart contract.

### Fields

| Name | Type | Description |
|---------|-----------|---------------------------------|
| address | `Field` | The address of the SlowTree contract |

## Functions

### at

Returns an instance of `SlowMap` at the specified address.

**Parameters**

| Name | Type | Description |
|----------|----------------|----------------------------|
| `address`| `AztecAddress` | The address of the SlowTree |

**Return**

| Name | Type | Description |
|-------|-----------|------------------------------|
| - | `SlowMap` | The `SlowMap` instance |

**Example**

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

### initialize

Initializes the `SlowMap`.

**Parameters**

| Name | Type | Description |
|-----------|-----------------|----------------------|
| `context` | `PublicContext` | The execution context |

**Return**

| Name | Type | Description |
|------|------|-------------|
| - | - | - |

**Example**

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

### read_at_pub

Reads a value at a specified index from a public function.

**Parameters**

| Name | Type | Description |
|-----------|-----------------|-----------------------|
| `context` | `PublicContext` | The execution context |
| `index` | `Field` | The index to read at |

**Return**

| Name | Type | Description |
|----------|--------|-----------------------|
| `result` | `Field`| The value at `index` |

**Example**

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

### read_at

Reads a value at a specified index from a private function.

**Parameters**

| Name | Type | Description |
|-----------|--------------------|------------------------|
| `context` | `PrivateContext` | The execution context |
| `index` | `Field` | The index to read at |

**Return**

| Name | Type | Description |
|----------|--------|-----------------------|
| `result` | `Field`| The value at `index` |

**Example**

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

### update_at_private

Updates a value at a specified index from a private function. Does not return anything.

**Parameters**

| Name | Type | Description |
|-------------|--------------------|------------------------|
| `context` | `PrivateContext` | The execution context |
| `index` | `Field` | The index to update |
| `new_value` | `Field` | The new value |

**Example**

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

## Updating from public

This is not a method in the interface as it can be done using regular Aztec.nr public storage update syntax.

**Example**

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

Loading