Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 17 additions & 50 deletions yellow-paper/docs/rollup-circuits/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@ Together with the [validating light node](../l1-smart-contracts/index.md), the r

To support this, we construct a single proof for the entire block, which is then verified by the validating light node.
This single proof consist of three main components:
It has **two** sub-trees for transactions, and **one** tree for L1 to L2 messages.
It has **two** sub-trees for transactions, and **one** tree for L1 to L2 messages.
The two transaction trees are then merged into a single proof and combined with the roots of the message tree to form the final proof and output.
Each of these trees are built by recursively combining proofs from a lower level of the tree.
This structure allows us to keep the workload of each individual proof small, while making it very parallelizable.
This works very well for the case where we want many actors to be able to participate in the proof generation.

Note that we have two different types of "merger" circuits, depending on what they are combining.
Note that we have two different types of "merger" circuits, depending on what they are combining.

For transactions we have:

- The `merge` rollup
- Merges two `base` rollup proofs OR two `merge` rollup proofs
- The `root` rollup
- Merges two `merge` rollup proofs

And for the message parity we have:

- The `root_parity` circuit
- Merges `N` `root` or `base_parity` proofs
- The `base_parity` circuit
- Merges `N` l1 to l2 messages in a subtree
- Merges `N` l1 to l2 messages in a subtree

In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs.
In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs.
Circles mark the different types of proofs, while squares mark the different circuit types.

```mermaid
Expand Down Expand Up @@ -138,7 +140,7 @@ graph BT

To understand what the circuits are doing and what checks they need to apply it is useful to understand what data is going into the circuits and what data is coming out.

Below is a figure of the data structures thrown around for the block proof creation.
Below is a figure of the data structures thrown around for the block proof creation.
Note that the diagram does not include much of the operations for kernels, but mainly the data structures that are used for the rollup circuits.

<!-- Missing `FeeContext` class definition in the diagram below -->
Expand All @@ -147,15 +149,13 @@ Note that the diagram does not include much of the operations for kernels, but m

<!-- NOTE: If you're editing this diagram, there will be other diagrams (e.g. in the state / circuits sections) that will need to be updated too. There are also class definitions in other sections which will need to be updated. -->

<!-- TODO(@spalladino): `contract_tree` in `PartialStateReference` and `ContractData` below -->
```mermaid
classDiagram
direction TB

class PartialStateReference {
note_hash_tree: Snapshot
nullifier_tree: Snapshot
contract_tree: Snapshot
public_data_tree: Snapshot
}

Expand Down Expand Up @@ -192,12 +192,6 @@ Header *-- ContentCommitment: content_commitment
Header *-- StateReference : state
Header *-- GlobalVariables : global_variables

class ContractData {
leaf: Fr
address: Address
portal: EthAddress
}

class Logs {
private: EncryptedLogs
public: UnencryptedLogs
Expand All @@ -212,11 +206,9 @@ class TxEffect {
note_hashes: List~Fr~
nullifiers: List~Fr~
l2_to_l1_msgs: List~Fr~
contracts: List~ContractData~
public_writes: List~PublicDataWrite~
logs: Logs
}
TxEffect *-- "m" ContractData: contracts
TxEffect *-- "m" PublicDataWrite: public_writes
TxEffect *-- Logs : logs

Expand Down Expand Up @@ -253,12 +245,6 @@ class PublicDataRead {
value: Fr
}

class NewContractData {
function_tree_root: Fr
address: Address
portal: EthAddress
}

class CombinedAccumulatedData {
aggregation_object: AggregationObject
read_requests: List~Fr~
Expand All @@ -268,7 +254,6 @@ class CombinedAccumulatedData {
nullified_note_hashes: List~Fr~

l2_to_l1_messages: List~Fr~
contracts: List~NewContractData~
public_update_requests: List~PublicDataUpdateRequest~
public_reads: List~PublicDataRead~
logs: Logs
Expand All @@ -278,28 +263,15 @@ class CombinedAccumulatedData {
start_public_data_root: Fr
end_public_data_root: Fr
}
CombinedAccumulatedData *-- "m" NewContractData: contracts
CombinedAccumulatedData *-- "m" PublicDataUpdateRequest: public_update_requests
CombinedAccumulatedData *-- "m" PublicDataRead: public_reads
CombinedAccumulatedData *-- Logs : logs

class ContractDeploymentData {
deployer_public_key: Point
constructor_vk_hash: Fr
constructor_args_hash: Fr
function_tree_root: Fr
salt: Fr
portal_address: Fr
}

class TxContext {
fee_context: FeeContext
is_contract_deployment: bool
chain_id: Fr
version: Fr
contract_deployment_data: ContractDeploymentData
}
TxContext *-- ContractDeploymentData: contract_deployment_data

class CombinedConstantData {
historical_header: Header
Expand Down Expand Up @@ -329,7 +301,6 @@ class StateDiffHints {
sorted_nullifier_indexes: List~Fr~
note_hash_subtree_sibling_path: List~Fr~,
nullifier_subtree_sibling_path: List~Fr~,
contract_subtree_sibling_path: List~Fr~,
public_data_sibling_path: List~Fr~,
}

Expand Down Expand Up @@ -415,26 +386,22 @@ RootRollupPublicInputs *--Header : header
```

:::info CombinedAccumulatedData
Note that the `CombinedAccumulatedData` contains elements that we won't be using throughout the rollup circuits.
Note that the `CombinedAccumulatedData` contains elements that we won't be using throughout the rollup circuits.
However, as the data is used for the kernel proofs (when it is build recursively), we will include it here anyway.
:::

:::warning TODO
Reconsider `ContractDeploymentData` in light of the newer (still being finalised) contract deployment flow
:::

Since the diagram can be quite overwhelming, we will go through the different data structures and what they are used for along with the three (3) different rollup circuits.

### Higher-level tasks

Before looking at the circuits individually, it can however be a good idea to recall the reason we had them in the first place.
Before looking at the circuits individually, it can however be a good idea to recall the reason we had them in the first place.
For this, we are especially interested in the tasks that span multiple circuits and proofs.

#### State consistency

While the individual kernels are validated on their own, they might rely on state changes earlier in the block.
For the block to be correctly validated, this means that when validating kernel $n$, it must be executed on top of the state after all kernels $<n$ have been applied.
For example, when kernel $3$ is executed, it must be executed on top of the state after kernels $0$, $1$ and $2$ have been applied.
While the individual kernels are validated on their own, they might rely on state changes earlier in the block.
For the block to be correctly validated, this means that when validating kernel $n$, it must be executed on top of the state after all kernels $<n$ have been applied.
For example, when kernel $3$ is executed, it must be executed on top of the state after kernels $0$, $1$ and $2$ have been applied.
If this is not the case, the kernel proof might be valid, but the state changes invalid which could lead to double spends.

It is therefore of the highest importance that the circuits ensure that the state is progressed correctly across circuit types and proofs.
Expand Down Expand Up @@ -466,19 +433,19 @@ graph LR

#### State availability

To ensure that state is made available, we could broadcast all of a block's input data as public inputs of the final root rollup proof, but a proof with so many public inputs would be very expensive to verify onchain.
To ensure that state is made available, we could broadcast all of a block's input data as public inputs of the final root rollup proof, but a proof with so many public inputs would be very expensive to verify onchain.

Instead, we can reduce the number of public inputs by committing to the block's body and iteratively "build" up the commitment at each rollup circuit iteration.
At the very end, we will have a commitment to the transactions that were included in the block (`TxsHash`), the messages that were sent from L2 to L1 (`OutHash`) and the messages that were sent from L1 to L2 (`InHash`).

To check that the body is published an Aztec node can simply reconstruct the hashes from available data.
To check that the body is published an Aztec node can simply reconstruct the hashes from available data.
Since we define finality as the point where the block is validated and included in the state of the [validating light node](../l1-smart-contracts/index.md), we can define a block as being "available" if the validating light node can reconstruct the commitment hashes.

Since the `InHash` is directly computed by the `Inbox` contract on L1, the data is obviously available to the contract without doing any more work.
Furthermore, the `OutHash` is a computed from a subset of the data in `TxsHash` so if it is possible to reconstruct `TxsHash` it is also possible to reconstruct `OutHash`.

Since we strive to minimize the compute requirements to prove blocks, we amortize the commitment cost across the full tree.
We can do so by building merkle trees of partial "commitments", whose roots are ultimately computed in the final root rollup circuit.
Since we strive to minimize the compute requirements to prove blocks, we amortize the commitment cost across the full tree.
We can do so by building merkle trees of partial "commitments", whose roots are ultimately computed in the final root rollup circuit.
Below, we outline the `TxsHash` merkle tree that is based on the `TxEffect`s and a `OutHash` which is based on the `l2_to_l1_msgs` (cross-chain messages) for each transaction.
While the `TxsHash` implicitly includes the `OutHash` we need it separately such that it can be passed to the `Outbox` for consumption by the portals with minimal work.

Expand Down Expand Up @@ -584,7 +551,7 @@ graph BT
K7 --> B3
```

While the `TxsHash` merely require the data to be published and known to L1, the `InHash` and `OutHash` needs to be computable on L1 as well.
While the `TxsHash` merely require the data to be published and known to L1, the `InHash` and `OutHash` needs to be computable on L1 as well.
This reason require them to be efficiently computable on L1 while still being non-horrible inside a snark - leading us to rely on SHA256.

## Next Steps
Expand Down
11 changes: 1 addition & 10 deletions yellow-paper/docs/rollup-circuits/root-rollup.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ This might practically happen through a series of "squisher" circuits that will
:::

## Overview
<!-- TODO(@spalladino): `contract_tree` in `PartialStateReference` and `ContractData` below -->

```mermaid
classDiagram
direction TB

class PartialStateReference {
note_hash_tree: Snapshot
nullifier_tree: Snapshot
contract_tree: Snapshot
public_data_tree: Snapshot
}

Expand Down Expand Up @@ -61,12 +60,6 @@ Header *-- ContentCommitment: content_commitment
Header *-- StateReference : state
Header *-- GlobalVariables : global_variables

class ContractData {
leaf: Fr
address: Address
portal: EthAddress
}

class Logs {
private: EncryptedLogs
public: UnencryptedLogs
Expand All @@ -81,11 +74,9 @@ class TxEffect {
note_hashes: List~Fr~
nullifiers: List~Fr~
l2_to_l1_msgs: List~Fr~
contracts: List~ContractData~
public_writes: List~PublicDataWrite~
logs: Logs
}
TxEffect *-- "m" ContractData: contracts
TxEffect *-- "m" PublicDataWrite: public_writes
TxEffect *-- Logs : logs

Expand Down
16 changes: 2 additions & 14 deletions yellow-paper/docs/state/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ A side-effect of this also means that if multiple users are "sharing" their note
## State Categories

<!--
Missing the L2->L1 messages (the new tree idea), which also form part of the state of the Aztec protocol.
Missing the L2->L1 messages (the new tree idea), which also form part of the state of the Aztec protocol.
Lasse: No. It is not state.

The verification keys of the core protocol circuits are technically (constant) state of the Aztec protocol.
Expand All @@ -83,17 +83,13 @@ To recall, the global state in Aztec is represented by a set of Merkle trees: th

<!-- NOTE: If you're editing this diagram, there will be other diagrams (e.g. in the rollup-circuits / circuits sections) that will need to be updated too. There are also class definitions in other sections which will need to be updated. -->


<!-- TODO(@spalladino): `contract_tree` in `PartialStateReference` and `ContractData` below -->

```mermaid
classDiagram
direction TB

class PartialStateReference {
note_hash_tree: Snapshot
nullifier_tree: Snapshot
contract_tree: Snapshot
public_data_tree: Snapshot
}

Expand Down Expand Up @@ -140,21 +136,13 @@ class PublicDataWrite {
value: Fr
}

class ContractData {
leaf: Fr
address: Address
portal: EthAddress
}

class TxEffect {
note_hashes: List~Fr~
nullifiers: List~Fr~
l2_to_l1_msgs: List~Fr~
contracts: List~ContractData~
public_writes: List~PublicDataWrite~
logs: Logs
}
TxEffect *-- "m" ContractData: contracts
TxEffect *-- "m" PublicDataWrite: public_writes
TxEffect *-- Logs : logs

Expand Down Expand Up @@ -221,4 +209,4 @@ State *-- PublicDataTree : public_data_tree

import DocCardList from '@theme/DocCardList';

<DocCardList />
<DocCardList />