|
| 1 | +# Private Kernel Circuit - Initial |
| 2 | + |
| 3 | +:::info Disclaimer |
| 4 | +This is a draft. These requirements need to be considered by the wider team, and might change significantly before a mainnet release. |
| 5 | +::: |
| 6 | + |
| 7 | +## Requirements |
| 8 | + |
| 9 | +In the **initial** kernel iteration, the process involves taking a transaction request and private call data, verifying their integrity, and preparing the necessary data for subsequent circuits to operate. This step is particularly beneficial due to its separation from the [inner private kernel circuit](./private-kernel-inner.md), as the first call lacks a "previous kernel" to process. Additionally, it executes tasks that are pertinent to a transaction and need only occur once. |
| 10 | + |
| 11 | +### Key Responsibilities Specific to this Circuit |
| 12 | + |
| 13 | +#### Validating the correspondence of function call with caller's intent. |
| 14 | + |
| 15 | +This entails ensuring that the following data from the private call aligns with the specifications in the transaction request: |
| 16 | + |
| 17 | +- Contract address. |
| 18 | +- [Function data](#function_data). |
| 19 | +- Function arguments. |
| 20 | + |
| 21 | +> Although it's not enforced in the protocol, it is customary to provide a signature signed over the transaction request and verify it in the first function call. This practice guarantees that only the party possessing the key(s) can authorize a transaction with the exact transaction request. |
| 22 | +
|
| 23 | +#### Verifying the legitimacy of the function as the entrypoint. |
| 24 | + |
| 25 | +- It must be a private function. |
| 26 | +- It must not be an internal function. |
| 27 | + |
| 28 | +#### Ensuring the function call is the first call. |
| 29 | + |
| 30 | +- It must not be a delegate call. |
| 31 | +- It must not be a static call. |
| 32 | + |
| 33 | +#### Ensuring transaction uniqueness. |
| 34 | + |
| 35 | +- It must emit the hash of the transaction request as the **first** nullifier. |
| 36 | + |
| 37 | +This nullifier serves multiple purposes: |
| 38 | + |
| 39 | +- Identifying a transaction. |
| 40 | +- Preventing the signature of a transaction request from being reused in another transaction. |
| 41 | +- Generating values that should be maintained within the transaction's scope. For example, it is utilized to compute the nonces for all the note hashes in a transaction. |
| 42 | + |
| 43 | +> Note that the final transaction data is not deterministic for a given transaction request. The production of new notes, the destruction of notes, and various other values are likely to change based on the time and conditions when a transaction is being composed. However, the intricacies of implementation should not be a concern for the entity initiating the transaction. |
| 44 | +
|
| 45 | +### Processing Private Function Call |
| 46 | + |
| 47 | +#### Ensuring the contract instance being called is deployed. |
| 48 | + |
| 49 | +It proves that the nullifier representing the contract exists in the contract tree. |
| 50 | + |
| 51 | +This nullifier is the contract address siloed with the address of a precompiled deployment contract. |
| 52 | + |
| 53 | +#### Ensuring the function being called exists in the contract. |
| 54 | + |
| 55 | +The contract address contains the contract class ID, which is a hash of the root of its function tree and additional values. This circuit leverages these characteristics to establish the validity of the function's association with the contract address. |
| 56 | + |
| 57 | +Each leaf of the function tree is a hash representing a function. The preimage includes: |
| 58 | + |
| 59 | +- Function data. |
| 60 | +- Hash of the verification key. |
| 61 | +- Hash of the function bytecode. |
| 62 | + |
| 63 | +To ensure the function's existence, the circuit executes the following steps: |
| 64 | + |
| 65 | +1. Computes the hash of the verification key. |
| 66 | +2. Calculates the function leaf: `hash(...function_data, vk_hash, bytecode_hash)` |
| 67 | +3. Derives the function tree root with the leaf and the specified sibling path. |
| 68 | +4. Computes the contract class ID using the function tree root and additional information. |
| 69 | +5. Generates the contract address using the contract class ID and other relevant details. |
| 70 | +6. Validates that the contract address matches the address specified in the private call data. |
| 71 | + |
| 72 | +#### Verifying the private function proof. |
| 73 | + |
| 74 | +It verifies that the private function was executed successfully with the provided proof data, verification key, and the public inputs of the private function circuit. |
| 75 | + |
| 76 | +#### Verifying the public inputs of the private function circuit. |
| 77 | + |
| 78 | +It ensures the private function circuit's intention by checking the following: |
| 79 | + |
| 80 | +- The contract address for each non-empty item in the following arrays must equal the current contract address: |
| 81 | + - Note hash contexts. |
| 82 | + - Nullifier contexts. |
| 83 | + - L2-to-L1 message contexts. |
| 84 | + - Read requests. |
| 85 | +- The portal contract address for each non-empty L2-to-L1 message context must equal the current portal contract address. |
| 86 | +- If the new contract contexts array is not empty, the contract address must equal the precompiled deployment contract address. |
| 87 | +- The historical data must match the one in the constant data. |
| 88 | + |
| 89 | +> Ensuring the alignment of the contract addresses is crucial, as it is later used to silo the value and to establish associations with values within the same contract. |
| 90 | +
|
| 91 | +#### Verifying the call requests. |
| 92 | + |
| 93 | +For both private and public call requests initiated in the current function call, it ensures that for each request at index _i_: |
| 94 | + |
| 95 | +- Its hash equals the value at index _i_ within the call request hashes array in private function circuit's public inputs. |
| 96 | +- Its caller context is either empty or aligns with the call context of the current function call, including: |
| 97 | + - _msg_sender_ |
| 98 | + - Storage contract address. |
| 99 | + |
| 100 | +> It is important to note that the caller context in a call request may be empty for standard calls. This precaution is crucial to prevent information leakage, particularly as revealing the _msg_sender_ to the public could pose security risks when calling a public function. |
| 101 | +
|
| 102 | +#### Verifying the counters. |
| 103 | + |
| 104 | +It verifies that each relevant value is associated with a legitimate counter. |
| 105 | + |
| 106 | +1. For the current call: |
| 107 | + |
| 108 | + - The _counter_start_ must be 0. |
| 109 | + - The _counter_end_ must be greater than the _counter_start_. |
| 110 | + |
| 111 | +2. For private call requests: |
| 112 | + |
| 113 | + - The _counter_end_ of each request must be greater than its _counter_start_. |
| 114 | + - The _counter_start_ of the first request must be greater than the _counter_start_ of the current call. |
| 115 | + - The _counter_start_ of the second and subsequent requests must be greater than the _counter_end_ of the previous request. |
| 116 | + - The _counter_end_ of the last request must be less than the _counter_end_ of the current call. |
| 117 | + |
| 118 | +3. For items in each ordered array created in the current call: |
| 119 | + |
| 120 | + - The counter of the first item much be greater than the _counter_start_ of the current call. |
| 121 | + - The counter of each subsequent item much be greater than the counter of the previous item. |
| 122 | + - The counter of the last item much be less than the _counter_end_ of the current call. |
| 123 | + |
| 124 | + The ordered arrays include: |
| 125 | + |
| 126 | + - Note hash contexts. |
| 127 | + - Nullifier contexts. |
| 128 | + - New contract contexts. |
| 129 | + - Read requests. |
| 130 | + - Public call requests. |
| 131 | + |
| 132 | + > Note that _counter_start_ is used in the above steps for public call requests to ensure their correct ordering. At this point, the _counter_end_ of public call request is unknown. Both counters will be [recalibrated](./private-kernel-tail.md#recalibrating-counters) in the tail circuit following the simulation of all public function calls. |
| 133 | +
|
| 134 | +### Validating Public Inputs |
| 135 | + |
| 136 | +#### Verifying the accumulated data. |
| 137 | + |
| 138 | +It verifies that the following values align with those in the private call data: |
| 139 | + |
| 140 | +- Log hashes. |
| 141 | +- Log lengths. |
| 142 | + |
| 143 | +#### Verifying the transient accumulated data. |
| 144 | + |
| 145 | +1. It ensures that the following arrays match those in the private call data: |
| 146 | + |
| 147 | + - Note hash contexts. |
| 148 | + - Nullifier contexts. |
| 149 | + - L2-to-L1 message contexts. |
| 150 | + - New contract contexts. |
| 151 | + - Read requests. |
| 152 | + - Public call requests. |
| 153 | + |
| 154 | +2. It checks that the following aligns with the array in the private call data, with items arranged in **reverse** order: |
| 155 | + |
| 156 | + - Private call requests. |
| 157 | + |
| 158 | + > It's important that the call requests are arranged in reverse order to ensure they are executed in chronological order. This becomes particularly crucial when calling a contract deployed earlier within the same transaction. |
| 159 | +
|
| 160 | +3. For the note hash contexts, it also verifies that each is associated with a nullifier counter, which is provided as a hint via the private inputs. The nullifier counter can be: |
| 161 | + |
| 162 | + - Zero: if the note is not nullified in the same transaction. |
| 163 | + - Greater than zero: if the note is nullified in the same transaction. |
| 164 | + - This value must be greater than the counter of the note hash. |
| 165 | + |
| 166 | + > Nullifier counters are used in the [reset private kernel circuit](./private-kernel-reset.md#verifying-read-requests) to ensure a read happens **before** a transient note is nullified. |
| 167 | +
|
| 168 | + > Zero can be used to indicate a non-existing transient nullifier, as this value can never serve as the counter of a nullifier. It corresponds to the _counter_start_ of the first function call. |
| 169 | +
|
| 170 | +#### Verifying the constant data. |
| 171 | + |
| 172 | +It verifies that: |
| 173 | + |
| 174 | +- The transaction context matches the one in the transaction request. |
| 175 | + |
| 176 | +> The historical data must align with the data used in the private function circuit, as verified [earlier](#verifying-the-public-inputs-of-the-private-function-circuit). |
| 177 | +
|
| 178 | +## Private Inputs |
| 179 | + |
| 180 | +### Transaction Request |
| 181 | + |
| 182 | +A transaction request represents the caller's intent. It contains: |
| 183 | + |
| 184 | +- Sender's address. |
| 185 | +- <a name="function_data">Function data</a>: |
| 186 | + |
| 187 | + - Function selector. |
| 188 | + - Function type (private/public/unconstrained). |
| 189 | + - A flag indicating whether the function is an internal function. |
| 190 | + |
| 191 | +- Hash of the function arguments. |
| 192 | +- Transaction context |
| 193 | + - A flag indicating whether it is a fee paying transaction. |
| 194 | + - A flag indicating whether it is a fee rebate transaction. |
| 195 | + - Chain ID. |
| 196 | + - Version of the transaction. |
| 197 | + |
| 198 | +### Private Call Data |
| 199 | + |
| 200 | +The private call data holds details about the current private function call: |
| 201 | + |
| 202 | +- Contract address. |
| 203 | +- Function data. |
| 204 | +- Private call requests. |
| 205 | +- Public call requests. |
| 206 | +- Private function circuit public inputs. |
| 207 | +- Proof of the private function circuit. |
| 208 | +- Verification key of the private function circuit. |
| 209 | +- Hash of the function bytecode. |
| 210 | + |
| 211 | +### Hints |
| 212 | + |
| 213 | +Data that aids in the verifications carried out in this circuit or later iterations: |
| 214 | + |
| 215 | +- Membership witness for the function leaf. |
| 216 | +- Membership witness for the contract leaf. |
| 217 | +- Transient note nullifier counters. |
| 218 | + |
| 219 | +## Public Inputs |
| 220 | + |
| 221 | +The structure of this public inputs aligns with that of the [inner private kernel circuit](./private-kernel-inner.md) and the [reset private kernel circuit](./private-kernel-reset.md). |
| 222 | + |
| 223 | +### Constant Data |
| 224 | + |
| 225 | +These are constants that remain the same throughout the entire transaction: |
| 226 | + |
| 227 | +- Historical data - representing the states of the block at which the transaction is constructed, including: |
| 228 | + - Hash of the global variables. |
| 229 | + - Roots of the trees: |
| 230 | + - Note hash tree. |
| 231 | + - Nullifier tree. |
| 232 | + - Contract tree. |
| 233 | + - L1-to-l2 message tree. |
| 234 | + - Public data tree. |
| 235 | +- Transaction context |
| 236 | + - A flag indicating whether it is a fee paying transaction. |
| 237 | + - A flag indicating whether it is a fee rebate transaction. |
| 238 | + - Chain ID. |
| 239 | + - Version of the transaction. |
| 240 | + |
| 241 | +### Accumulated Data |
| 242 | + |
| 243 | +It contains the result from the current function call: |
| 244 | + |
| 245 | +- Log hashes. |
| 246 | +- Log lengths. |
| 247 | + |
| 248 | +### Transient Accumulated Data |
| 249 | + |
| 250 | +It includes transient data accumulated during the execution of the transaction up to this point: |
| 251 | + |
| 252 | +- Note hash contexts. |
| 253 | +- Nullifier contexts. |
| 254 | +- L2-to-L1 message contexts. |
| 255 | +- New contract contexts. |
| 256 | +- Read requests. |
| 257 | +- Private call requests. |
| 258 | +- Public call requests. |
0 commit comments