Skip to content

Commit 5acba2d

Browse files
AztecBotaztec-bot
authored andcommitted
docs: document initializerless accounts (v5-next backport of #24512)
Backport of #24512 ("docs: document initializerless accounts") into `v5-next`, requested by Alejo in Slack. ## What this adds (same as the original PR) - **New concept page** `foundational-topics/accounts/deployment.md` ("Account Deployment"): the standard initialize-and-deploy flow vs the initializerless flow, how the signing key is committed into the address via `immutables_hash`, and the trade-offs (no deploy cost/delay; signing key fixed forever; per-PXE local setup; `getDeployMethod()` throws). - **New "Create an initializerless account" section** in `aztec-js/how_to_create_account.md` with the `createSchnorrInitializerlessAccount` snippet and caveats. - **Cross-links** from `fees.md`, `wallets.md`, `contract_creation.md`, and `aztec-nr/framework-description/immutables.md`. ## How the backport differs from the original - The original PR mirrored all changes into `developer_versioned_docs/version-v5.0.0-rc.2/`. That snapshot does not exist on `v5-next` (the only snapshot here is `version-v4.3.0`, which documents the v4 line and must not describe a v5-only feature), so this backport touches **only the current docs** under `docs/docs-developers/`. Git's directory-rename detection tried to remap the mirrored copies into the v4.3.0 snapshot during the cherry-pick; those were dropped deliberately. - Everything else is the original commit cherry-picked verbatim; the only diff-vs-original differences are context lines where `v5-next` prose already diverged from `next`. ## Notes - Unlike `next`, `createSchnorrInitializerlessAccount` **does** exist in this branch's `yarn-project` (verified), so the fenced snippet could be converted to an `#include_code` example here as a follow-up. Kept as a fenced block for a faithful backport. - Verified all new internal links resolve to files present on `v5-next`, and `initializerless` is already in `docs-words.txt` on this branch. Refs #24512. --- *Created by [claudebox](https://claudebox.work/v2/sessions/045227c21dcc966b) · group: `slackbot`* (cherry picked from commit 7534604)
1 parent b2dd2c8 commit 5acba2d

6 files changed

Lines changed: 89 additions & 4 deletions

File tree

docs/docs-developers/docs/aztec-js/how_to_create_account.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,29 @@ The secret is used to derive the account's encryption keys, and the salt ensures
3030
Save the `secret` and `salt` values securely. You need both to recover access to your account. If you lose them, you will permanently lose access to the account and any assets it holds.
3131
:::
3232

33+
## Create an initializerless account
34+
35+
Alternatively, create an [initializerless account](../foundational-topics/accounts/deployment.md), which needs no deployment transaction at all:
36+
37+
```typescript
38+
const secret = Fr.random();
39+
const salt = Fr.random();
40+
const account = await wallet.createSchnorrInitializerlessAccount(secret, salt);
41+
console.log("Account address:", account.address.toString());
42+
```
43+
44+
An initializerless account commits its signing public key into the address itself (through the instance's `immutables_hash`), so there is no onchain state to initialize. Creating the account registers it locally in the PXE, and it is ready to use immediately: skip the deployment section below entirely. Fees are only needed for the account's first real transaction, paid with any of the usual [payment methods](./how_to_pay_fees.md).
45+
46+
Two things to keep in mind:
47+
48+
- The signing key cannot be changed later. A new key means a new address.
49+
- Calling `getDeployMethod()` on an initializerless account throws, since there is nothing to deploy.
50+
51+
See [account deployment](../foundational-topics/accounts/deployment.md) for how this works and how to choose between the two account types.
52+
3353
## Deploy the account
3454

35-
New accounts must be deployed before they can send transactions. Deployment requires paying fees.
55+
Accounts created with `createSchnorrAccount` must be deployed before they can send transactions (initializerless accounts skip this step). Deployment requires paying fees.
3656

3757
### Using the Sponsored FPC
3858

@@ -70,5 +90,5 @@ Confirm the account was deployed successfully. Substitute the account variable f
7090

7191
- [Deploy contracts](./how_to_deploy_contract.md) with your new account
7292
- [Send transactions](./how_to_send_transaction.md) from an account
73-
- Learn about [account abstraction](../foundational-topics/accounts/index.md)
93+
- Learn about [account abstraction](../foundational-topics/accounts/index.md) and [account deployment](../foundational-topics/accounts/deployment.md)
7494
- Implement [authentication witnesses](./how_to_use_authwit.md)

docs/docs-developers/docs/aztec-nr/framework-description/immutables.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ Initialization cost is completely eliminated (no constructor transaction). The p
3131
## Getting started
3232

3333
For installation instructions, usage examples, and a reference implementation of an initializerless Schnorr account contract, see the [aztec-immutables-macro README](https://github.com/defi-wonderland/aztec-immutables-macro/tree/dev).
34+
35+
The protocol ships a built-in account contract using the same pattern: see [account deployment](../../foundational-topics/accounts/deployment.md) for how initializerless accounts work and [creating accounts](../../aztec-js/how_to_create_account.md#create-an-initializerless-account) for using them from Aztec.js.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: Account Deployment
3+
tags: [accounts]
4+
description: How Aztec accounts come into existence, from the standard initializer plus deployment flow to initializerless accounts that need no onchain transaction at all.
5+
references:
6+
[
7+
"noir-projects/noir-contracts/contracts/account/schnorr_initializerless_account_contract/src/main.nr",
8+
"noir-projects/noir-contracts/contracts/account/schnorr_account_contract/src/main.nr",
9+
]
10+
---
11+
12+
## How accounts come into existence
13+
14+
Every account in Aztec is a [contract instance](../contract_creation.md), and its address is computed deterministically from its instantiation parameters. There are two ways to make an account usable:
15+
16+
1. **The standard flow**: create the account locally, then send a deployment transaction that runs its initializer.
17+
2. **The initializerless flow**: create the account locally, and that is it. No deployment transaction is ever sent.
18+
19+
This page explains both flows and when to choose each.
20+
21+
## The standard flow: initialize and deploy
22+
23+
A regular account contract (for example the default Schnorr account) stores its signing public key in private state. Writing that state requires running the contract's constructor, a [private initializer function](../../aztec-nr/framework-description/functions/attributes.md#initializer-functions-initializer), which in turn requires sending a transaction to the network and paying [fees](../fees.md) for it.
24+
25+
The address commits to that pending initialization: the constructor call's selector and arguments are hashed into the instance's `initialization_hash`, which is folded into the address derivation. This is why the address can be computed, shared, and even receive funds before the deployment transaction is sent, and why the account only becomes able to send transactions after it.
26+
27+
## Initializerless accounts
28+
29+
An initializerless account removes the deployment transaction entirely. Instead of storing the signing key in private state through an initializer, the key is committed directly into the address: the instance's `immutables_hash` field is set to the hash of the signing public key, and `immutables_hash` participates in address derivation just like `initialization_hash` does.
30+
31+
Since the address itself is the commitment to the signing key, there is no onchain state to create:
32+
33+
- The account contract has no initializer. Its `constructor` is an unconstrained utility function that runs only in the PXE: it checks that the provided public key hashes to the instance's `immutables_hash` and stores the key in the PXE's local store.
34+
- When the account later authorizes a transaction, its entrypoint loads the key from the local store and proves in the private kernel that the key's hash matches the `immutables_hash` committed in the address. Tampering with the local key is not possible without changing the address.
35+
36+
Creating an initializerless account is therefore a purely local operation: the wallet computes the address, registers the contract instance in the PXE, and runs the utility constructor through a simulation. No transaction is sent, no fee is paid, and the account can start transacting as soon as it has a way to pay for its first real transaction (for example a [Sponsored FPC](../fees.md#payment-methods) or a Fee Juice balance at its address).
37+
38+
The genesis-funded test accounts in the local network are initializerless Schnorr accounts: their addresses receive Fee Juice at genesis, and wallets materialize them locally without any deployment.
39+
40+
## Trade-offs
41+
42+
Initializerless accounts are a good default when the account's authorization logic only depends on parameters that never change:
43+
44+
- **No deployment cost or delay.** The account is usable the moment it is created, which makes onboarding flows and receive-only addresses cheap.
45+
- **The signing key is fixed forever.** The key is baked into the address, so there is no way to rotate it. A new key means a new address. The default Schnorr account offers no key rotation either, but account contracts that keep keys in state can be designed to support it.
46+
- **Local setup is still required per PXE.** A fresh PXE does not know about the account until the wallet registers the instance and runs the utility constructor again. This is a purely offline step with no fee, but it must happen in every new environment before the account can be used.
47+
- **There is no deployment method.** Calling `getDeployMethod()` on an initializerless account throws, since there is nothing to deploy.
48+
49+
Use the standard flow when the account contract needs an initializer: for example when it takes arbitrary constructor arguments or stores its authorization material in private notes.
50+
51+
## Using initializerless accounts
52+
53+
- In Aztec.js, call `createSchnorrInitializerlessAccount(secret, salt)` on your wallet. See [creating accounts](../../aztec-js/how_to_create_account.md#create-an-initializerless-account).
54+
- In the CLI, pass the account type: `aztec-wallet create-account -t schnorr_initializerless`. The command registers the account locally and returns immediately, with no deployment transaction.
55+
- In Aztec.nr, the same address-immutables pattern can be applied to your own contracts. See [immutables](../../aztec-nr/framework-description/immutables.md).
56+
57+
## Next steps
58+
59+
- [Create an account in Aztec.js](../../aztec-js/how_to_create_account.md)
60+
- [Understand fees and payment methods](../fees.md)
61+
- [Contract creation and address derivation](../contract_creation.md)

docs/docs-developers/docs/foundational-topics/contract_creation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ A contract instance includes:
5555
- `deployer`: Optional address of the contract deployer. Zero for universal deployment
5656
- `original_contract_class_id`: Identifier of the contract class the instance was deployed with. Updating the instance to a new class via the ContractInstanceRegistry does not change this value, since it is part of the address preimage
5757
- `initialization_hash`: Hash of the selector and arguments to the constructor
58-
- `immutables_hash`: Hash of the contract's compile-time immutable state
58+
- `immutables_hash`: Hash of the contract's compile-time immutable state. [Initializerless accounts](./accounts/deployment.md) use it to commit the signing key into the address
5959
- `public_keys`: Public keys participating in address derivation (nullifier, incoming viewing, outgoing viewing, tagging, message-signing, and fallback keys). Only the incoming viewing key is held as an elliptic curve point; the other five are held as their `hash_public_key` digests.
6060

6161
### Instance Address

docs/docs-developers/docs/foundational-topics/fees.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ In `aztec.js`, the `L1FeeJuicePortalManager` class handles the L1 side (token ap
103103

104104
### Payment methods
105105

106-
An account with Fee Juice can pay for its transactions directly. A new account can even pay for its own deployment transaction, provided Fee Juice was bridged to its address before deployment.
106+
An account with Fee Juice can pay for its transactions directly. A new account can even pay for its own deployment transaction, provided Fee Juice was bridged to its address before deployment. [Initializerless accounts](./accounts/deployment.md) skip the deployment transaction entirely, so they only need fees once they send their first real transaction.
107107

108108
Alternatively, accounts can use [fee-paying contracts (FPCs)](../aztec-js/how_to_pay_fees.md#use-fee-payment-contracts) to pay for transactions. An FPC holds its own Fee Juice balance to pay the protocol, and can accept other tokens from users in exchange.
109109

docs/docs-developers/docs/foundational-topics/wallets.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ A wallet must support at least one specific account contract implementation, whi
2121

2222
Note that users must be able to receive funds in Aztec before deploying their account. A wallet should let a user generate a [deterministic complete address](./accounts/keys.md#address-derivation) without having to interact with the network, so they can share it with others to receive funds. This requires that the wallet pins a specific contract implementation, its initialization arguments, a deployment salt, and the user's keys. These values yield a deterministic address, so when the account contract is actually deployed, it is available at the precalculated address. Once the account contract is deployed, the user can start sending transactions using it as the transaction origin.
2323

24+
Some account contracts avoid deployment altogether: [initializerless accounts](./accounts/deployment.md) commit their signing key into the address itself, so the wallet only needs to register them locally before they can start transacting.
25+
2426
## Transaction lifecycle
2527

2628
Every transaction in Aztec is broadcast to the network as a zero-knowledge proof of correct execution, in order to preserve privacy. This means that transaction proofs are generated on the wallet and not on a remote node. This is one of the biggest differences with regard to EVM chain wallets.

0 commit comments

Comments
 (0)