-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(yellow-paper): Contract deployment
Adds section on contract deployment, as well as contract trees to state and delegate calls.
- Loading branch information
1 parent
48e2e3d
commit 2a98685
Showing
6 changed files
with
144 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
sidebar_position: 3.2 | ||
--- | ||
|
||
# Delegate calls | ||
|
||
Delegate calls are function calls against a [contract class identifier](../contract-deployment/classes.md) instead of an instance. Any call, synchronous or asynchronous, can be made as a delegate call. The behavior of a delegate call is to execute the function code in the specified class identifier but on the context of the current instance. This opens the door to script-like executions and upgradeable contracts. Delegate calls are based on [EIP7](https://eips.ethereum.org/EIPS/eip-7). | ||
|
||
At the protocol level, a delegate call is identified by a `is_delegate_call` flag in the `CircuitPublicInputs` of the `CallStackItem`. The `contract_address` field is reinterpreted as a contract class instead. When executing a delegate call, the kernel preserves the values of the `CallContext` `msgSender` and `storageContractAddress`. | ||
|
||
At the contract level, a caller can initiate a delegate call via a `delegateCallPrivateFunction` or `delegateCallPublicFunction` oracle call. The caller is responsible for asserting that the returned `CallStackItem` has the `is_delegate_call` flag correctly set. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Contract classes | ||
|
||
A contract class is a collection of related unconstrained, private, and public functions. Contract classes don't have state, they just define code. | ||
|
||
## Rationale | ||
|
||
Contract classes simplify the process of reusing code by enshrining implementations as a first-class citizen at the protocol. Given multiple contract instances that rely on the same class, the class needs to be declared only once, reducing the deployment cost for all contract instances. Classes also simplify the process of upgradeability. Classes decouple state from code, making it easier for an instance to switch to different code while retaining its state. | ||
|
||
:::info | ||
Read the following discussions for additional context: | ||
- [Abstracting contract deployment](https://forum.aztec.network/t/proposal-abstracting-contract-deployment/2576) | ||
- [Implementing contract upgrades](https://forum.aztec.network/t/implementing-contract-upgrades/2570) | ||
- [Contract classes, upgrades, and default accounts](https://forum.aztec.network/t/contract-classes-upgrades-and-default-accounts/433) | ||
::: | ||
|
||
## Structure | ||
|
||
The structure of a contract class is defined as: | ||
|
||
| Field | Type | Description | | ||
|----------|----------|----------| | ||
| version | u8 | Version identifier. Initially one, bumped for any changes to the contract class struct. | | ||
| registerer_address | AztecAddress | Address of the canonical contract used for registering this class. | | ||
| artifact_hash | Field | Hash of the entire contract artifact, including compiler information, proving backend, and all generated ACIR and Brillig. The specification of this hash is left to the compiler and not enforced by the protocol. | | ||
| constructor_function | PrivateFunction | Constructor for instances of this class. | | ||
| private_functions | PrivateFunction[] | List of private functions. | | ||
| public_functions | PublicFunction[] | List of public functions. | | ||
| unconstrained_functions | UnconstrainedFunction[] | List of unconstrained functions. | | ||
|
||
<!-- TODO: Do we need the artifact hash, if we're including the artifact hash of each individual function? --> | ||
<!-- NOTE: I'm deliberately omitting the portal bytecode hash here --> | ||
|
||
### Private Function | ||
|
||
| Field | Type | Description | | ||
|----------|----------|----------| | ||
| function_selector | u32 | Selector of the function. Calculated as the hash of the method name and arguments. | | ||
| vk_hash | Field | Hash of the verification key associated to this private function. | | ||
| salt | Field | Optional value for salting the bytecode of a function. | | ||
| bytecode_hash | Field | Hash of the compiled function artifact, including all generated ACIR and Brillig. | | ||
| optional_bytecode | Buffer | Optional bytecode for the function. Private function bytecode can be kept private if desired and only broadcasted to participants of the contract. | | ||
|
||
### Public and Unconstrained Function | ||
|
||
| Field | Type | Description | | ||
|----------|----------|----------| | ||
| function_selector | u32 | Selector of the function. Calculated as the hash of the method name and arguments. | | ||
| bytecode_hash | Field | Hash of the compiled function artifact, including all generated Brillig code. | | ||
| bytecode | Buffer | Full bytecode for the function. Must hash to the `artifact_hash`. | | ||
|
||
<!-- TODO: Expand on the bytecode commitment scheme and bytecode_hash, both here and for private fns. --> | ||
|
||
## Registration | ||
|
||
A contract class is registered by calling a `register` function in a canonical `ClassRegisterer` contract. The `register` function receives a `ContractClass` struct as defined above, and performs the following checks: | ||
|
||
<!-- TODO: Should register be private or public? Or both? --> | ||
|
||
- `version` is 1 for the initial release | ||
- `registerer_address` equals to self | ||
- `bytecode` for each function hashes to the `bytecode_hash` | ||
|
||
The `register` function then: | ||
|
||
- Emits the `ContractClass` struct as unencrypted events. | ||
- Computes the class identifier as the hash of the `ContractClass` object. | ||
- Returns the computed class identifier as a `new_contract_classes` public input. | ||
|
||
<!-- TODO: Define the format of the unencrypted event --> | ||
<!-- TODO: Define how to compute the hash --> | ||
|
||
The kernel circuit then validates that the contract emitting the new contract classes is the canonical `ClassRegisterer`, and emits the `new_contract_classes` so they are added to the contract class tree in global state. Upon seeing a new contract class registration in a mined transaction, nodes are expected to store the contract class, so they can retrieve it when executing a public function for that class. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
title: Contract Deployment | ||
--- | ||
|
||
# Contract Deployment | ||
|
||
Contracts in Aztec are deployed as _instances_ of a contract _class_. Deploying a new contract then requires first registering the _class_, if it has not been registered before, and then actually creating an _instance_ that references the class. Both classes and instances are committed to in dedicated indexed trees in the global state, and are created via a call to a canonical class registry or instance deployer contract respectively. | ||
|
||
import DocCardList from '@theme/DocCardList'; | ||
|
||
<DocCardList /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Contract instances | ||
|
||
A contract instance is a concrete deployment of a [contract class](./classes.md). A contract instance has state, both private and public, as well as an address that acts as identifier, and can be called into. A contract instance always references a contract class, that dictates what code it executes when called. | ||
|
||
## Structure | ||
|
||
The structure of a contract instance is defined as: | ||
|
||
| Field | Type | Description | | ||
|----------|----------|----------| | ||
| version | u8 | Version identifier. Initially one, bumped for any changes to the contract instance struct. | | ||
| deployer_address | AztecAddress | Address of the canonical contract used for deploying this instance. | | ||
| salt | Field | User-generated pseudorandom value for uniqueness. | | ||
| contract_class_id | Field | Identifier of the contract class for this instance. | | ||
| contract_args_hash | Field | Hash of the arguments to the constructor. | | ||
| portal_contract_address | EthereumAddress | Optional address of the L1 portal contract. | | ||
| public_keys | PublicKeys | Optional struct of public keys used for encryption and nullifying by this contract. | | ||
|
||
<!-- TODO: Define the structure of public_keys --> | ||
|
||
## Deployment | ||
|
||
A new contract instance can be created by calling a private `deploy` function in a canonical `Deployer` contract. This function receives a `ContractInstance` struct as described above, and executes the following actions: | ||
|
||
<!-- TODO: Should deploy be private or public? Or both? --> | ||
|
||
- Validates the referenced `contract_class_id` exists. | ||
- Computes the resulting contract address from the hash of the contract instance. | ||
- Emits the address in the `new_contract_instances` public inputs. | ||
- Calls the constructor with the preimage of the supplied `contract_args_hash`. | ||
- Emits an unencrypted event with the address and its preimage. | ||
|
||
The kernel circuit validates that the contract emitting the `new_contract_instances` is the canonical `Deployer`, and emits those values so they can be added to the global contract instances tree. Upon seeing a new contract deployed event, nodes are expected to store the address and preimage. | ||
|
||
<!-- TODO: Define how address is computed --> | ||
<!-- TODO: Define what info is emitted --> | ||
<!-- TODO: Define the format of the unencrypted event --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Contracts Trees | ||
|
||
Global state includes two trees for contracts: a [_contract classes_](../contract-deployment/classes.md) tree and a [_contract instances_](../contract-deployment/instances.md) tree. These trees store contract class identifiers and contract instance addresses respectively. Both trees are implemented as [indexed Merkle trees](./tree_impls.md#indexed-merkle-trees) in order to support non-membership proofs: | ||
|
||
- A public call to an undeployed contract instance needs to provably fail. | ||
- A re-deployment of the same instance must provably fail. | ||
- A public deployment of an instance with an unregistered contract class need to provably fail. | ||
- A delegate call to an unregistered class must provably fail. | ||
|
||
<!-- NOTE: We should be able to turn the contract class into an append-only merkle tree if we don't include delegate calls nor public contract deployments. --> | ||
|
||
The identifiers for new classes and instances are emitted by canonical application contracts, which are validated and re-emitted by the kernel circuit. Uniqueness in their respective trees is checked on insertion. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters