For the complete documentation index, see llms.txt.
Skip to main content
Version: Alpha / Testnet (v6.0.0)

v6.0.0

Overview​

Migration difficulty: high, mostly because almost everything you pull from moved.

The v6 rollup is a fresh deployment starting from genesis. Run your v6 node with a new, empty data directory: no v5 chain state carries over.

Two things to settle before you start: every artifact location changed, and the ACVM_* configuration variables were renamed with no fallback. A node doing real proving fails to start on the old names; one that is not falls back to WASM simulation and starts anyway, much slower, so a clean startup is not evidence that your configuration migrated.

When to switch on Mainnet​

The v6 rollup becomes canonical on Mainnet when governance executes the v6 upgrade proposal. The earliest execution time is Monday 26 October 2026, 08:00 UTC. Until then, v5 is the canonical rollup and your v5 node keeps doing the work.

You have two options.

Option 1 (recommended): stand up a v6 node in standby now. Start a v6 node next to your v5 node any time before the execution date. At startup it compares the canonical rollup's genesis archive root, VK tree root and protocol contracts hash with its own. While v5 is still canonical they do not match, so the node enters standby mode: it serves only a health endpoint (which reports healthy, so liveness probes pass), polls L1 once a minute, and uses very few resources. Once the v6 rollup becomes canonical, the node logs Compatible rollup found at <address>. Exiting standby mode. and starts normally, with no action from you. You see this at startup:

Rollup at 0x... is incompatible: ... Entering standby mode. Will poll every 60s for a compatible rollup...

If the v6 node shares a host with the v5 node, give it its own data directory, container name, AZTEC_PORT and P2P_PORT. Standby binds the HTTP port as soon as it starts, and the node binds the P2P port when it leaves standby, so reusing the v5 values makes the v6 node fail at one of those two moments.

Standby only works for a node that follows the canonical rollup, which is the default. Do not pin ROLLUP_VERSION to the v6 rollup's version: the v6 rollup is not in the registry until the proposal executes, so the node cannot look it up and fails to start.

Keep the v5 node running until the v6 node has left standby and is attesting.

Option 2: upgrade at execution time. Stop your v5 node and start the v6 node on Monday 26 October 2026 at 08:00 UTC, or as soon after as the proposal executes. This works, but your sequencer does nothing until the v6 node has started and synced, and you have to be there at the time.

High-availability setups sharing a signing database

v5 nodes delete other rollups' signing records from a shared PostgreSQL HA signing database when they start. If a v5 replica restarts after the v6 replica has started signing, the v6 replica loses its double-signing protection. Give the v6 replicas their own database, or do not restart v5 replicas after the switch to v6. See Signing history and rollup upgrades.

New repository, image and package locations​

Everything moved. Old locations keep what was already published, so existing v5 setups keep working, but nothing new lands there.

v5 and earlierv6
Source repositoryAztecProtocol/aztec-packagesaztec-labs-eng/aztec-node
Docker imagesaztecprotocol/aztecazteclabs/aztec
Prover agent imageaztecprotocol/aztec-prover-agentazteclabs/aztec-prover-agent
npm (client packages)@aztec/*@aztec-labs/*
npm (foundation packages)@aztec/bb.js, @aztec/noir-*@aztec-foundation/*
Aztec.nrin the monorepoaztec-labs-eng/aztec-nr

Update your image references first. A compose file or Helm values still pointing at aztecprotocol/aztec will pull a v5 image and fail against a v6 network.

- image: aztecprotocol/aztec:5.2.0
+ image: azteclabs/aztec:6.0.0

The @aztec npm scope keeps the packages published for earlier versions, so an existing project pinned to a v5 version continues to resolve. The packages now depend on upstream viem instead of the @aztec/viem fork.

Behaviour changes​

World-state history retention uses one policy​

--world-state-history-retention <policy> ($WS_HISTORY_RETENTION)

Replace WS_NUM_HISTORIC_CHECKPOINTS=N or WS_NUM_HISTORIC_BLOCKS=N with WS_HISTORY_RETENTION=rolling:N. Replace values below 1 with WS_HISTORY_RETENTION=archive. The former --world-state-checkpoint-history flag is removed.

  • rolling:N retains the latest N finalized checkpoints and all newer state. The default is rolling:64.
  • pinned:N retains checkpoint N and every later checkpoint permanently, including every block of the pinned checkpoint.
  • archive retains all history from genesis and disables history pruning.

Rolling counts and pinned checkpoint numbers must be positive integers. Increasing a rolling window accumulates history as the chain advances. Pinned and archive modes reject databases missing required history, even with SYNC_MODE=force-snapshot. Use a fresh world-state database to rebuild missing history. Fresh databases try compatible snapshots before replaying from genesis; pinned mode only accepts snapshots in the pinned checkpoint or earlier, and archive mode requires full history.

ACVM_* configuration renamed to NOIR_EXECUTE_*​

Protocol circuits are now executed with noir's noir-execute rather than the acvm binary, and the configuration naming the executor follows the tool. What you point it at is unchanged.

OldNew
ACVM_BINARY_PATHNOIR_EXECUTE_BINARY_PATH
ACVM_WORKING_DIRECTORYNOIR_EXECUTE_WORKING_DIRECTORY
--sequencer.acvmBinaryPath--sequencer.noirExecuteBinaryPath
--sequencer.acvmWorkingDirectory--sequencer.noirExecuteWorkingDirectory
--proverNode.acvmBinaryPath--proverNode.noirExecuteBinaryPath
--proverNode.acvmWorkingDirectory--proverNode.noirExecuteWorkingDirectory
- ACVM_BINARY_PATH=/usr/src/labs-aztec-toolchain/bin/noir-execute
- ACVM_WORKING_DIRECTORY=/usr/src/acvm
+ NOIR_EXECUTE_BINARY_PATH=/usr/src/labs-aztec-toolchain/bin/noir-execute
+ NOIR_EXECUTE_WORKING_DIRECTORY=/usr/src/noir-execute

There is no fallback to the old names. A prover agent exits with Requested real proving but no path to bb or noir-execute binaries provided; a prover node or sequencer configured for real proofs throws from BBNativeRollupProver.new when it tries to stat an undefined path. Only a node running without real proofs survives, by falling back to WASM simulation, which is much slower, so a node that appears to start may still be badly degraded.

If you run the release image it sets the new variables itself, and its default working directory moves from /usr/src/acvm to /usr/src/noir-execute. Check any values you override.

A trace-capable L1 endpoint is required by default​

ETHEREUM_ALLOW_NO_DEBUG_HOSTS now defaults to false.

FlagEnvironment VariablePreviousNew
--archiver.ethereumAllowNoDebugHostsETHEREUM_ALLOW_NO_DEBUG_HOSTStruefalse

At startup the node checks that the endpoint it traces with (ETHEREUM_DEBUG_HOSTS, or ETHEREUM_HOSTS when that is unset) serves debug_traceTransaction or trace_transaction. It used to log a warning and start when neither worked. It now refuses to start, with an error naming ETHEREUM_ALLOW_NO_DEBUG_HOSTS.

A checkpoint published through a non-standard contract, rather than by a direct call to the rollup, cannot be read from the transaction calldata alone: the node needs a trace to recover it. A node without one starts normally and then stops syncing at the first such checkpoint, until it is pointed at a trace-capable endpoint and restarted. Failing at startup surfaces the problem before the node is relied on.

Migration: point ETHEREUM_DEBUG_HOSTS at an endpoint that serves trace methods (see L1 RPC requirements). If you accept the risk of stalling, set ETHEREUM_ALLOW_NO_DEBUG_HOSTS=true to keep the old behaviour.

Attester-initiated sequencer exits​

A position can now be exited by its attester, not only by its withdrawer. Exits can also be batched: each attester signs an exit authorization, and one relayer submits them all in a single transaction. This is what makes it practical to exit tens or hundreds of positions, for example as a staking provider.

The stake still goes to the position's withdrawer, never to the attester. An attester-initiated exit starts the exit delay; the withdrawer then names the recipient, and anyone can finalize once the delay has passed. Attester-initiated exits are rate-limited to about 5% of the sequencer set per rolling window, only work on the canonical rollup, and so on Mainnet only after the v6 upgrade executes.

See Exiting a sequencer for the full procedure, the limits, and troubleshooting. In short:

# Each attester signs an authorization, appended to one file
aztec sign-attester-exit --private-key $ATTESTER_KEY --attester $ATTESTER \
--rollup $ROLLUP --l1-chain-id $L1_CHAIN_ID --deadline $DEADLINE \
--output exits.json --append

# Simulate, then submit with any funded key
aztec initiate-withdraw-by-attester-batch --dry-run --authorizations exits.json \
--rollup $ROLLUP --l1-chain-id $L1_CHAIN_ID --l1-rpc-urls $L1_RPC
aztec initiate-withdraw-by-attester-batch --authorizations exits.json \
--rollup $ROLLUP --l1-chain-id $L1_CHAIN_ID --l1-rpc-urls $L1_RPC \
--private-key $RELAYER_KEY

aztec initiate-withdraw-by-attester exits a single position in a transaction sent from the attester key itself.

Three functions are live on the rollup:

FunctionWhat it does
initiateWithdrawByAttester(address)Exit one position. Caller must be the attester.
initiateWithdrawByAttesterBatch(...)Relay many attester-signed exits. Reverts if the rate limit cannot fit the whole batch.
initiateWithdrawByAttesterBatchUpToLimit(...)Relay many attester-signed exits, processing only as many from the start of the list as the rate limit allows and leaving the rest for later.

Both batch functions still revert the whole transaction if any entry is invalid: an expired deadline, a bad signature, an attester that is already exiting or has no stake. Run --dry-run before submitting. Pass --up-to-limit to the batch command to use the UpToLimit function.

Calling the contract directly​

If you cannot use the CLI, call the rollup with cast. Exit a single position, signed and submitted by the attester:

cast send $ROLLUP "initiateWithdrawByAttester(address)" $ATTESTER \
--private-key $ATTESTER_KEY --rpc-url $L1_RPC

Batching needs an EIP-712 signature per attester. The domain is { name: "Aztec Rollup", version: "1", chainId: <L1 chain id>, verifyingContract: <rollup> } and the type is AttesterExit(address attester,uint256 deadline). Sign one per position:

cast wallet sign --private-key $ATTESTER_KEY --data '{
"domain":{"name":"Aztec Rollup","version":"1","chainId":'$L1_CHAIN_ID',"verifyingContract":"'$ROLLUP'"},
"types":{"AttesterExit":[{"name":"attester","type":"address"},{"name":"deadline","type":"uint256"}]},
"primaryType":"AttesterExit",
"message":{"attester":"'$ATTESTER'","deadline":"'$DEADLINE'"}
}'

Then relay them. Each entry is (attester, deadline, (v, r, s)), and the relayer pays the gas, so the submitting key need not be an attester:

cast send $ROLLUP \
"initiateWithdrawByAttesterBatchUpToLimit((address,uint256,(uint8,bytes32,bytes32))[])" \
"[($ATTESTER_0,$DEADLINE,($V0,$R0,$S0)),($ATTESTER_1,$DEADLINE,($V1,$R1,$S1))]" \
--private-key $RELAYER_KEY --rpc-url $L1_RPC

deadline is a unix timestamp and must be in the future. Each attester may appear only once per batch.

Withdrawer-initiated exits are unchanged.

remove-l1-validator and sequencers remove require --recipient​

aztec remove-l1-validator and aztec sequencers remove now require --recipient, the address that receives the withdrawn stake. Previously both always named the attester's own address as the recipient, sending the stake to the hot attester key (for delegated stake, a key the provider holds), and a recipient cannot be changed once set.

Migration: add --recipient [RECIPIENT_ADDRESS] to any script that calls remove-l1-validator or sequencers remove. Without it both commands fail before sending anything. The same command, sent from the withdrawer key, names the recipient after an attester-initiated exit.

Provers can skip full-epoch proving​

A new prover node setting stops the node from proving complete epochs on its own:

--proverNode.proverNodeDisableFullEpochProving ($PROVER_NODE_DISABLE_FULL_EPOCH_PROVING)

The default is false, so nothing changes unless you set it. With it set, the prover node logs Full epoch proving disabled at startup and only proves the partial epochs requested through its startProof admin method. Use it to run a prover that serves paid partial-epoch proofs (for example, for early withdrawals) without competing for full epoch proofs.

Change the log level without a restart​

The node admin config has a new logLevel key. Set it with aztecAdmin_setConfig, using the same format as LOG_LEVEL, and read it back with aztecAdmin_getConfig:

curl -X POST http://localhost:8880 \
-H 'Content-Type: application/json' \
-H 'x-api-key: [ADMIN_API_KEY]' \
-d '{"jsonrpc":"2.0","method":"aztecAdmin_setConfig","params":[{"logLevel":"debug;trace:sequencer,p2p"}],"id":1}'

The change applies to the node process immediately, including loggers created later. It does not reach processes the node spawns, and a restart reverts to LOG_LEVEL.

Publishers must afford the L1 transaction before work starts​

Nodes now check that a publisher holds enough ETH for its L1 transaction before doing the work behind it. The amount checked is a worst case: the transaction's gas limit times the max fee per gas, plus blob fees, at current L1 fees. At a 1 gwei base fee a proposal needs a few thousandths of an ETH.

  • Sequencers: if no publisher for the proposer can afford a checkpoint proposal, the node skips the slot before building or gossiping anything. It logs an error with each publisher's balance and the required amount, and records the insufficient_publisher_balance reason on aztec.sequencer.checkpoint.precheck_failed_count. Governance and slashing votes are still attempted. If a publisher can afford the proposal but not the votes bundled with it, the votes are dropped and the proposal is sent alone.
  • Provers: a prover node still proves an epoch while no publisher can afford the proof submission, but holds the finished proof back instead of sending it. It retries every 12 seconds and submits as soon as a publisher is funded, until the proof submission window closes. aztec.prover_node.proof_submission_unaffordable_count counts the held back proofs. Nothing changes when proof publishing is disabled.
  • Selection: a publisher with a recently mined transaction is no longer ranked below an idle one with less ETH, so a dust-funded idle publisher can no longer win every proposal. A publisher whose transaction was rejected for insufficient funds is skipped until its balance increases, or for at most five minutes.

Publisher balances are checked every minute​

Sequencers and prover nodes now read every publisher's balance once a minute, whether or not the publisher has sent anything, and price a reference transaction at current L1 fees: the first checkpoint proposal of an epoch for a sequencer, an epoch proof submission for a prover. At startup the node logs a Publisher balances line with every publisher's balance, at error level if none can afford the reference transaction. While that lasts, it logs No publisher can afford a proposal (or an epoch proof) at most every 10 minutes, naming the publisher to fund and how much ETH it is missing. The skipped proposal and held back proof errors name them too.

A warning is logged when a publisher's balance falls below a multiple of the cost of the reference transaction:

--sequencer.publisherLowBalanceWarningMultiplier <value> ($PUBLISHER_LOW_BALANCE_WARNING_MULTIPLIER)
--proverNode.publisherLowBalanceWarningMultiplier <value> ($PUBLISHER_LOW_BALANCE_WARNING_MULTIPLIER)

The default is 4. If you use automatic top-ups, set PUBLISHER_FUNDING_THRESHOLD above the warning level; the node warns if it is not. Top-ups are now checked every minute instead of every 2 minutes.

Metric changes (Prometheus names):

  • aztec_l1_publisher_balance_eth is now recorded every minute for every publisher, instead of only after a transaction is sent. Alerts on it now fire for a publisher that has never sent, or stopped sending because it cannot afford to. It gains an aztec_l1_tx_scope label (sequencer or prover).
  • New aztec_l1_publisher_sends_affordable: how many reference transactions each publisher's balance covers at current fees. Alert when it drops below 1.
  • New aztec_l1_publisher_required_balance_eth: the cost of one reference transaction at current fees.
  • New aztec_l1_publisher_funder_balance_eth: the balance of the funding account used for automatic top-ups.
  • aztec_l1_balance_eth is deprecated and will be removed in a later release. Use aztec_l1_publisher_balance_eth instead.
  • aztec_l1_gas_price_wei and aztec_l1_blob_base_fee_wei are now exported. They were defined before but never reached the exporter.

See Metrics reference for example alert rules.

New node RPC methods​

Two additions to the JSON-RPC surface. Both are additive; nothing was removed.

MethodWhat it is for
aztec_getTxEffectMembershipWitnessMembership proof for a transaction's effects.
aztec_getValidatorStatsBatchValidator statistics for several attesters in one call.

Both currently render under "Other methods" in the node API reference because the generator has no grouping for them yet.

Upgrade checklist​

  1. Point your image references at azteclabs/aztec and azteclabs/aztec-prover-agent.
  2. Rename ACVM_* to NOIR_EXECUTE_* in your environment, compose files or Helm values, before starting a v6 node.
  3. Confirm any overridden working directory matches the new default if you rely on the release image.
  4. Give the v6 node a new, empty data directory. The v6 rollup starts from genesis.
  5. Fund your sequencer and prover publishers. A node whose publishers cannot afford the L1 transaction skips the proposal or holds back the proof submission. Alert on aztec_l1_publisher_sends_affordable, and move any alert or dashboard on aztec_l1_balance_eth to aztec_l1_publisher_balance_eth.
  6. Check that ETHEREUM_DEBUG_HOSTS (or ETHEREUM_HOSTS, if you leave it unset) serves debug_traceTransaction or trace_transaction. A v6 node refuses to start without one unless you set ETHEREUM_ALLOW_NO_DEBUG_HOSTS=true.
  7. On Mainnet, start the v6 node before the upgrade executes and let it wait in standby, leaving ROLLUP_VERSION unset. Keep the v5 node running until the v6 node has left standby and is attesting.
  8. If you run HA signing on a shared PostgreSQL database, give the v6 replicas their own database or do not restart v5 replicas after the switch to v6.

Full release notes​

For the developer-facing changes in this release (the npm scope moves in detail, the aztec-nr repository move, Aztec.js artifact and return-type changes, and the removed CLI commands), see the migration notes.