Skip to content

Commit

Permalink
docs(yellow-paper): circuits (AztecProtocol#3782)
Browse files Browse the repository at this point in the history
Please provide a paragraph or two giving a summary of the change,
including relevant motivation and context.

# Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if
the PR is ready to merge.
- [ ] If the pull request requires a cryptography review (e.g.
cryptographic algorithm implementations) I have added the 'crypto' tag.
- [ ] I have reviewed my diff in github, line by line and removed
unexpected formatting changes, testing logs, or commented-out code.
- [ ] Every change is related to the PR description.
- [ ] I have
[linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
this pull request to relevant issues (if any exist).
  • Loading branch information
LeilaWang authored Jan 9, 2024
1 parent 28faee4 commit 8734a32
Show file tree
Hide file tree
Showing 10 changed files with 1,332 additions and 1,070 deletions.
136 changes: 136 additions & 0 deletions yellow-paper/docs/circuits/high-level-topology.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# High Level Topology

:::info Disclaimer
This is a draft. These requirements need to be considered by the wider team, and might change significantly before a mainnet release.
:::

## Overview

A transaction begins with a call to a private function, which may invoke nested calls to other private and public functions. The entire set of private function calls is executed in a secure environment, and their proofs are validated and aggregated by private kernel circuits. Meanwhile, any public function calls triggered from private functions will be enqueued. The proofs for these calls, along with those from the nested public function calls, are generated and processed through public kernel circuits in any entity possessing the correct contexts.

Once all functions in a transaction are executed, the accumulated data is outputted from a tail circuit. These values are then inserted or updated to the trees within the base rollup circuit. The merge rollup circuit facilitates the merging of two rollup proofs. Repeating this merging process enables the inclusion of more transactions in a block. Finally, the root rollup circuit produces the final proof, which is subsequently submitted and validated onchain.

To illustrate, consider a transaction involving the following functions, where circles depict private functions, and squares denote public functions:

```mermaid
flowchart LR
f0([f0]) --> f1([f1])
f0 --> f2([f2])
f0 --> f3([f3])
f1 -.-> F0
F0 --> F1
F0 --> F2
F2 --> F3
f3 --> f4([f4])
f3 -.-> F4
f3 --> f5([f5])
```

This transaction contains 6 private functions (f0 to f5) and 5 public functions (F0 to F4), with `f0` being the entrypoint. The entire transaction is processed as follows:

```mermaid
flowchart TB
subgraph Transaction A
subgraph Private Functions
f0([f0])
f1([f1])
f2([f2])
f3([f3])
f4([f4])
f5([f5])
end
subgraph Public Functions
F0
F1
F2
F3
F4
end
end
subgraph Transaction C
init2(...)
tail2(Tail Private Kernel)
init2 -.-> tail2
end
subgraph Transaction B
init1(...)
tail1(Tail Private Kernel)
init1 -.-> tail1
end
subgraph Public Kernel
INIT0(Initial Public Kernel)
INNER0(Inner Public Kernel)
INNER1(Inner Public Kernel)
INNER2(Inner Public Kernel)
INNER3(Inner Public Kernel)
TAIL0(Tail Public Kernel)
INIT0 --> INNER0
INNER0 --> INNER1
INNER1 --> INNER2
INNER2 --> INNER3
INNER3 --> TAIL0
end
subgraph Private Kernel
init0(Initial Private Kernel)
inner0(Inner Private Kernel)
inner1(Inner Private Kernel)
inner2(Inner Private Kernel)
reset0(Reset Private Kernel)
inner3(Inner Private Kernel)
inner4(Inner Private Kernel)
reset1(Reset Private Kernel)
tail0(Tail Private Kernel)
init0 --> inner0
inner0 --> inner1
inner1 --> inner2
inner2 --> reset0
reset0 --> inner3
inner3 --> inner4
inner4 --> reset1
reset1 --> tail0
end
f0 --> init0
f1 --> inner0
f2 --> inner1
f3 --> inner2
f4 --> inner3
f5 --> inner4
F0 --> INIT0
F1 --> INNER0
F2 --> INNER1
F3 --> INNER2
F4 --> INNER3
subgraph Rollup
BR0(Base Rollup)
BR1(Base Rollup)
BR2(Base Rollup)
BR3(Base Rollup)
MR0(Merge Rollup)
MR1(Merge Rollup)
MR2(Merge Rollup)
MR3(Merge Rollup)
ROOT(Root Rollup)
end
tail0 --> INIT0
TAIL0 --> BR0
tail1 --> BR1
tail2 --> BR2
BR0 --> MR0
BR1 --> MR0
BR2 --> MR1
BR3 --> MR1
MR0 --> MR2
MR1 --> MR2
MR2 --> ROOT
MR3 --> ROOT
```

A few things to note:

- A transaction always starts with an [initial private kernel circuit](./private-kernel-initial.md).
- An [inner private kernel circuit](./private-kernel-inner.md) won't be required if there is only one private function in a transaction.
- A [reset private kernel circuit](./private-kernel-reset.md) can be executed between two private kernel circuits to "reset" transient data. The reset process can be repeated as needed.
- Public functions are "enqueued" when invoked from a private function. Public kernel circuits will be executed after the completion of all private kernel iterations.
- A [base rollup circuit](../rollup-circuits/base_rollup.md) can accept either a [tail public kernel circuit](./public-kernel-tail.md), or a [tail private kernel circuit](./private-kernel-tail.md) in cases where no public functions are present in the transaction.
- A [merge rollup circuit](../rollup-circuits/merge_rollup.md) can merge two base rollup circuits or two merge rollup circuits.
- The final step is the execution of the [root rollup circuit](../rollup-circuits/root_rollup.md), which combines two base rollup circuits or two merge rollup circuits.
89 changes: 65 additions & 24 deletions yellow-paper/docs/circuits/private-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ This is a draft. These requirements need to be considered by the wider team, and

## Requirements

A private function circuit is a custom circuit tailored to the needs of a specific application. This circuit should be designed to handle private data processing while generating public inputs that safeguard the application and account's intentions without compromising sensitive information.
Private function circuits represent smart contract functions that modify the Aztec private state trees. They serve as untrusted, third-party code that is executed as part of evaluating an Aztec transaction.

The logic of this circuit is flexible, yet its public inputs must adhere to a specific format.
The logic of each private function circuit is tailored to the needs of a particular application or scenario, yet its public inputs must adhere to a specific format. This circuit should be designed to handle private data processing while generating public inputs that safeguard the application and account's intentions without compromising sensitive information.

## Private Inputs

Expand All @@ -18,28 +18,69 @@ The private inputs of a private function circuit are customizable.

The public inputs of a private function circuit will be incorporated into the private inputs of a private kernel circuit. Private kernel circuits leverage these public inputs, coupled with proof data and verification key from a private function circuit, to prove the correct execution of a private function.

It must adhere to the following format:

| Field | Type | Description |
| ---------------------------------- | -------------------------- | ---------------------------------------------------------------------- |
| _call_context_ | _CallContext_ | Context of the call corresponding to this function execution. |
| _args_hash_ | _field_ | Hash of the function arguments. |
| _return_values_ | [_field_; C] | Return values of this function call. |
| _read_requests_ | [_ReadRequest_; C] | Requests to read a note in the note hash tree. |
| _note_hash_contexts_ | [_NoteHashContext_; C] | New note hashes created in this function call. |
| _nullifier_contexts_ | [_NullifierContext_; C] | New nullifiers created in this function call. |
| _l2_to_l1_msg_contexts_ | [_L2L1MessageContext; C] | New L2 to L1 messages created in this function call. |
| _new_contract_contexts_ | [_ContractDataContext_; C] | Data of contracts deployed in this function call. |
| _encrypted_logs_hash_ | [_field_; N] | Hash of the encrypted logs emitted in this function call. |
| _unencrypted_logs_hash_ | [_field_; N] | Hash of the unencrypted logs emitted in this function call. |
| _encrypted_log_preimages_length_ | [_field_; N] | Length of the encrypted log preimages emitted in this function call. |
| _unencrypted_log_preimages_length_ | [_field_; N] | Length of the unencrypted log preimages emitted in this function call. |
| _private_call_stack_hashes_ | [_field_; C] | Hashes of the private function calls initiated by this function. |
| _public_call_stack_hashes_ | [_field_; C] | Hashes of the public function calls initiated by this function. |
| _block_header_ | _BlockHeader_ | Information about the trees used for the transaction. |
| _chain_id_ | _field_ | Chain ID of the transaction. |
| _version_ | _field_ | Version of the transaction. |
The following format defines the ABI that is used by the private kernel circuit when processing private function public inputs:

| Field | Type | Description |
| ---------------------------------- | ------------------------------------ | ---------------------------------------------------------------------- |
| _call_context_ | _[CallContext](#callcontext)_ | Context of the call corresponding to this function execution. |
| _args_hash_ | _field_ | Hash of the function arguments. |
| _return_values_ | [_field_; _C_] | Return values of this function call. |
| _read_requests_ | [_[ReadRequest](#readrequest)_; _C_] | Requests to read notes in the note hash tree. |
| _note_hashes_ | [_[NoteHash](#notehash)_; _C_] | New note hashes created in this function call. |
| _nullifiers_ | [_[Nullifier](#nullifier)_; _C_] | New nullifiers created in this function call. |
| _l2_to_l1_messages_ | [_field_; _C_] | New L2 to L1 messages created in this function call. |
| _encrypted_logs_hash_ | _field_ | Hash of the encrypted logs emitted in this function call. |
| _unencrypted_logs_hash_ | _field_ | Hash of the unencrypted logs emitted in this function call. |
| _encrypted_log_preimages_length_ | _field_ | Length of the encrypted log preimages emitted in this function call. |
| _unencrypted_log_preimages_length_ | _field_ | Length of the unencrypted log preimages emitted in this function call. |
| _private_call_stack_item_hashes_ | [_field_; _C_] | Hashes of the private function calls initiated by this function. |
| _public_call_stack_item_hashes_ | [_field_; _C_] | Hashes of the public function calls initiated by this function. |
| _block_header_ | _[BlockHeader](#blockheader)_ | Information about the trees used for the transaction. |
| _chain_id_ | _field_ | Chain ID of the transaction. |
| _version_ | _field_ | Version of the transaction. |

> The above **C**s represent constants defined by the protocol. Each **C** might have a different value from the others.
> The above **N**s represent the number of _field_ of a hash. Its value depends on the hash function chosen by the protocol.
## Types

#### _CallContext_

| Field | Type | Description |
| -------------------------- | -------------- | ----------------------------------------------------------------------- |
| _msg_sender_ | _AztecAddress_ | Address of the caller contract. |
| _storage_contract_address_ | _AztecAddress_ | Address of the contract against which all state changes will be stored. |
| _portal_contract_address_ | _AztecAddress_ | Address of the portal contract to the storage contract. |
| _is_delegate_call_ | _bool_ | A flag indicating whether the call is a delegate call. |
| _is_static_call_ | _bool_ | A flag indicating whether the call is a static call. |

#### _ReadRequest_

| Field | Type | Description |
| ----------- | ------- | -------------------------------------- |
| _note_hash_ | _field_ | Hash of the note to be read. |
| _counter_ | _field_ | Counter at which the request was made. |

#### _NoteHash_

| Field | Type | Description |
| --------- | ------- | ------------------------------------------- |
| _value_ | _field_ | Hash of the note. |
| _counter_ | _field_ | Counter at which the note hash was created. |

#### _Nullifier_

| Field | Type | Description |
| --------- | ------- | ------------------------------------------- |
| _value_ | _field_ | Value of the nullifier. |
| _counter_ | _field_ | Counter at which the nullifier was created. |

#### _BlockHeader_

| Field | Type | Description |
| ----------------------------- | ------- | ----------------------------------------------------------------------------------------------- |
| _note_hash_tree_root_ | _field_ | Root of the note hash tree. |
| _nullifier_tree_root_ | _field_ | Root of the nullifier tree. |
| _l1_to_l2_messages_tree_root_ | _field_ | Root of the l1-to-l2 messages tree. |
| _public_data_tree_root_ | _field_ | Root of the public data tree. |
| _archive_tree_root_ | _field_ | Root of the state roots tree archived at the block prior to when the transaction was assembled. |
| _global_variables_hash_ | _field_ | Hash of the previous global variables. |
Loading

0 comments on commit 8734a32

Please sign in to comment.