Skip to content

Commit

Permalink
docs: Update contract deployment section in YP (AztecProtocol#4290)
Browse files Browse the repository at this point in the history
Update contract deployment section in YP

---------

Co-authored-by: iAmMichaelConnor <[email protected]>
  • Loading branch information
spalladino and iAmMichaelConnor authored Jan 30, 2024
1 parent fd27808 commit e99a882
Show file tree
Hide file tree
Showing 5 changed files with 363 additions and 95 deletions.
7 changes: 7 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@
"memdown",
"memfs",
"Merkle",
"merkleization",
"merkleized",
"merkleizing",
"messagebox",
"mimc",
"mktemp",
Expand All @@ -140,6 +143,7 @@
"noirup",
"nullifer",
"offchain",
"onchain",
"otterscan",
"outdir",
"overlayfs",
Expand All @@ -148,6 +152,7 @@
"parallelizable",
"Pedersen",
"permissionless",
"permissionlessly",
"persistable",
"pids",
"pkgs",
Expand All @@ -156,6 +161,7 @@
"pnat",
"Pokeable",
"preauthenticated",
"precompute",
"preimage",
"preimages",
"prestat",
Expand Down Expand Up @@ -216,6 +222,7 @@
"typecheck",
"typegen",
"typeparam",
"undeployed",
"unexclude",
"unexcluded",
"unprefixed",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,8 @@ contract DiversifiedAccount
return address_preimage.deployer_address
```

<!-- TODO: The implementation above hinges on whether `deployer_address` for a contract is the actual deployer, or is the ContractDeployer contract. -->

Given the contract does not require initialization since it has no constructor, it can be used by its owner without being actually deployed, which reduces the setup cost.

<!-- TODO: The above requires that we implement "using a contract without deploying it if it has no constructor", or "constructor abstraction", both of which are a bit controversial. -->

## Discarded Approaches

An alternative approach was to introduce a new type of call, a diversified call, that would allow the caller to impersonate any address they can derive from their own, for an enshrined derivation mechanism. Account contracts could use this opcode, as opposed to a regular call, to issue calls on behalf on their diversified and stealth addresses. However, this approach failed to account for calls made back to the account contracts, in particular authwit checks. It also required protocol changes, introducing a new type of call which could be difficult to reason about, and increased attack surface. The only benefit over the approach chosen is that it would require one less extra function call to hop from the user's main account contract to the diversified or stealth one.
47 changes: 38 additions & 9 deletions yellow-paper/docs/addresses-and-keys/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,44 @@ An address is computed as the hash of the following fields:
<!-- prettier-ignore -->
| Field | Type | Description |
|----------|----------|----------|
| version | u8 | Version identifier. Initially one, bumped for any changes to the contract instance struct. |
| deployer_address | AztecAddress | Address of the deployer for 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. |

The `PublicKeys` struct can vary depending on the format of keys used by the address, but it is suggested it includes the master keys defined above: $\Npkm$, $\Tpkm$, $\Ivpkm$, $\Ovpkm$.
| `salt` | `Field` | User-generated pseudorandom value for uniqueness. |
| `deployer` | `AztecAddress` | Optional address of the deployer of the contract. |
| `contract_class_id` | `Field` | Identifier of the contract class for this instance. |
| `initialization_hash` | `Field` | Hash of the selector and arguments to the constructor. |
| `portal_contract_address` | `EthereumAddress` | Address of the L1 portal contract, zero if none. |
| `public_keys_hash` | `Field` | Hash of the struct of public keys used for encryption and nullifying by this contract, zero if no public keys. |

Storing these fields in the address preimage allows any part of the protocol to check them by recomputing the hash and verifying that the address matches. Examples of these checks are:
- Sending an encrypted note to an undeployed account, which requires the sender app to check the recipient's public key given their address. This scenario also requires the recipient to share with the sender their public key and rest of preimage.
- Having the kernel circuit verify that the code executed at a given address matches the one from the class.
- Asserting that the initialization hash matches the function call in the contract constructor.
- Checking the portal contract address when sending a cross-chain message.

:::warning
We may remove the `portal_contract_address` as a first-class citizen.
:::

The hashing scheme for the address should then ensure that checks that are more frequent can be done cheaply, and that data shared out of band is kept manageable. We define the hash to be computed as follows:

```
salted_initialization_hash = pedersen([salt, initialization_hash, deployer as Field, portal_contract_address as Field], GENERATOR__SALTED_INITIALIZATION_HASH)
partial_address = pedersen([contract_class_id, salted_initialization_hash], GENERATOR__CONTRACT_PARTIAL_ADDRESS_V1)
address = pedersen([public_keys_hash, partial_address], GENERATOR__CONTRACT_ADDRESS_V1)
```

The `public_keys` array can vary depending on the format of keys used by the address, but it is suggested it includes the master keys defined above: $\Npkm$, $\Tpkm$, $\Ivpkm$, $\Ovpkm$. A suggested hashing is:
```
public_keys_hash = pedersen([
nullifier_pubkey.x, nullifier_pubkey.y,
tagging_pubkey.x, tagging_pubkey.y,
incoming_view_pubkey.x, incoming_view_pubkey.y,
outgoing_view_pubkey.x, outgoing_view_pubkey.y
], GENERATOR__PUBLIC_KEYS)
```

This recommended hash format is compatible with the [encryption precompiles](./precompiles.md#encryption-and-tagging-precompiles) initially defined in the protocol and advertised in the canonical [registry](../private-message-delivery/registry.md) for private message delivery. An address that chooses to use a different format for its keys will not be compatible with apps that rely on the registry for note encryption. Nevertheless, new precompiles introduced in future versions of the protocol could use different public keys formats.

<!-- TODO(cryptography): Can we restrict "x" components of public keys to all be the same sign, so we don't need to encode "y"'s signs? -->

## Derive siloed keys

Expand Down
Loading

0 comments on commit e99a882

Please sign in to comment.