> For the complete documentation index, see [llms.txt](/llms.txt)

# v4.x (Upgrade from Ignition)

## Overview

**Migration difficulty**: High

## Breaking changes

### Node.js upgraded to v24

Node.js minimum version changed from v22 to v24.12.0.

### Bot fee padding configuration renamed

The bot configuration for fee padding has been renamed from "base fee" to "min fee".

**v3.x:**

```bash
--bot.baseFeePadding <value>          ($BOT_BASE_FEE_PADDING)
```

**v4.0.0:**

```bash
--bot.minFeePadding <value>           ($BOT_MIN_FEE_PADDING)
```

**Migration**: Update your configuration to use the new flag name and environment variable.

### L2Tips API restructured with checkpoint information

The `getL2Tips()` RPC endpoint now returns a restructured response with additional checkpoint tracking.

**v3.x response:**

```json
{
  "latest": { "number": 100, "hash": "0x..." },
  "proven": { "number": 98, "hash": "0x..." },
  "finalized": { "number": 95, "hash": "0x..." }
}
```

**v4.0.0 response:**

```json
{
  "proposed": { "number": 100, "hash": "0x..." },
  "checkpointed": {
    "block": { "number": 99, "hash": "0x..." },
    "checkpoint": { "number": 10, "hash": "0x..." }
  },
  "proven": {
    "block": { "number": 98, "hash": "0x..." },
    "checkpoint": { "number": 9, "hash": "0x..." }
  },
  "finalized": {
    "block": { "number": 95, "hash": "0x..." },
    "checkpoint": { "number": 8, "hash": "0x..." }
  }
}
```

**Migration**:

* Replace `tips.latest` with `tips.proposed`
* For `checkpointed`, `proven`, and `finalized` tips, access block info via `.block` (e.g., `tips.proven.block.number`)

### Block gas limits reworked

The byte-based block size limit has been removed and replaced with field-based blob limits and automatic gas budget computation from L1 rollup limits.

**Removed:**

```bash
--maxBlockSizeInBytes <value>                    ($SEQ_MAX_BLOCK_SIZE_IN_BYTES)
```

**Changed to optional (now auto-computed from L1 if not set):**

```bash
--maxL2BlockGas <value>                          ($SEQ_MAX_L2_BLOCK_GAS)
--maxDABlockGas <value>                          ($SEQ_MAX_DA_BLOCK_GAS)
```

**New (proposer):**

```bash
--perBlockAllocationMultiplier <value>         ($SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER)
--maxTxsPerCheckpoint <value>                     ($SEQ_MAX_TX_PER_CHECKPOINT)
```

**New (validator):**

```bash
--validateMaxL2BlockGas <value>                   ($VALIDATOR_MAX_L2_BLOCK_GAS)
--validateMaxDABlockGas <value>                   ($VALIDATOR_MAX_DA_BLOCK_GAS)
--validateMaxTxsPerBlock <value>                  ($VALIDATOR_MAX_TX_PER_BLOCK)
--validateMaxTxsPerCheckpoint <value>             ($VALIDATOR_MAX_TX_PER_CHECKPOINT)
```

**Migration**: Remove `SEQ_MAX_BLOCK_SIZE_IN_BYTES` from your configuration. Per-block L2 and DA gas budgets are now derived automatically as `(checkpointLimit / maxBlocks) * multiplier`, where the multiplier defaults to 2. You can still override `SEQ_MAX_L2_BLOCK_GAS` and `SEQ_MAX_DA_BLOCK_GAS` explicitly, but they will be capped at the checkpoint-level limits. Validators can now set independent per-block and per-checkpoint limits via the `VALIDATOR_` env vars; when not set, only checkpoint-level protocol limits are enforced.

### Setup phase allow list requires function selectors

The transaction setup phase allow list now enforces function selectors, restricting which specific functions can run during setup on whitelisted contracts. Previously, any public function on a whitelisted contract or class was permitted.

The semantics of the environment variable `TX_PUBLIC_SETUP_ALLOWLIST` have changed:

**v3.x:**

```bash
--txPublicSetupAllowList <value>     ($TX_PUBLIC_SETUP_ALLOWLIST)
```

The variable fully **replaced** the hardcoded defaults. Format allowed entries without selectors: `I:address`, `C:classId`.

**v4.0.0:**

```bash
--txPublicSetupAllowListExtend <value>  ($TX_PUBLIC_SETUP_ALLOWLIST)
```

The variable now **extends** the hardcoded defaults (which are always present). Selectors are now mandatory. An optional flags segment can be appended for additional validation:

```text
I:address:selector[:flags]
C:classId:selector[:flags]
```

Where `flags` is a `+`-separated list of:

* `os` — `onlySelf`: only allow calls where msg\_sender == contract address
* `rn` — `rejectNullMsgSender`: reject calls with a null msg\_sender
* `cl=N` — `calldataLength`: enforce exact calldata length of N fields

Example: `C:0xabc:0x1234:os+cl=4`

**Migration**: If you were using `TX_PUBLIC_SETUP_ALLOWLIST`, ensure all entries include function selectors. Note the variable now adds to defaults rather than replacing them. If you were not setting this variable, no action is needed — the hardcoded defaults now include the correct selectors automatically.

### Token removed from default setup allowlist

Token class-based entries (`_increase_public_balance` and `transfer_in_public`) have been removed from the default public setup allowlist. FPC-based fee payments using custom tokens no longer work out of the box.

This change was made because Token class IDs change with aztec-nr releases, making the allowlist impossible to keep up to date with new library releases. In addition, `transfer_in_public` requires complex additional logic to be built into the node to prevent mass transaction invalidation attacks. **FPC-based fee payment with custom tokens won't work on mainnet alpha**.

**Migration**: Node operators who need FPC support must manually add Token entries via `TX_PUBLIC_SETUP_ALLOWLIST`. Example:

```bash
TX_PUBLIC_SETUP_ALLOWLIST="C:<tokenClassId>:<increaseBalanceSelector>:os+cl=3,C:<tokenClassId>:<transferInPublicSelector>:cl=5"
```

Replace `<tokenClassId>` with the deployed Token contract class ID and `<increaseBalanceSelector>`/`<transferInPublicSelector>` with the respective function selectors. Keep in mind that this will only work on local network setups, since even if you as an operator add these entries, other nodes will not have them and will not pick up these transactions.

### Sequencer environment variable renames

Several sequencer environment variables have been renamed:

| Old variable                             | New variable                                                          |
| ---------------------------------------- | --------------------------------------------------------------------- |
| `SEQ_TX_POLLING_INTERVAL_MS`             | `SEQ_POLLING_INTERVAL_MS`                                             |
| `SEQ_MAX_L1_TX_INCLUSION_TIME_INTO_SLOT` | `SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT`                            |
| `SEQ_MAX_TX_PER_BLOCK`                   | `SEQ_MAX_TX_PER_CHECKPOINT`                                           |
| `SEQ_MAX_BLOCK_SIZE_IN_BYTES`            | Removed (see [Block gas limits reworked](#block-gas-limits-reworked)) |

**Migration**: Search your configuration for the old variable names and replace them. The node will not recognize the old names.

### Double signing slashing

New slashable offenses have been introduced for duplicate proposals and duplicate attestations. Penalty amounts are currently set to 0, but the detection infrastructure is active.

If you run redundant sequencer nodes, you **must** enable high-availability signing with PostgreSQL to prevent accidental double signing:

```bash
VALIDATOR_HA_SIGNING_ENABLED=true
VALIDATOR_HA_DATABASE_URL=postgresql://<user>:<password>@<host>:<port>/<database>
VALIDATOR_HA_NODE_ID=<unique-id-per-node>
```

Run the database migration before starting your nodes:

```bash
aztec migrate-ha-db up --database-url <url>
```

**Migration**: If you run a single node, no action is required. If you run redundant nodes for high availability, configure HA signing immediately. See the [High Availability Sequencers](/operate/operators/setup/high_availability_sequencers.md) guide for details.

### Blob-only data publication

Transaction data is now published entirely via EIP-4844 blobs. The calldata fallback has been removed.

Your consensus client (e.g., Lighthouse, Prysm) must run as a **supernode** or **semi-supernode** to make blobs available for retrieval. Standard pruning configurations will not retain blobs long enough.

You should also configure blob file stores for redundancy:

```bash
BLOB_FILE_STORE_URLS=<comma-separated-read-urls>
BLOB_FILE_STORE_UPLOAD_URL=<upload-url>
BLOB_ARCHIVE_API_URL=<archive-api-url>
```

**Migration**: Ensure your consensus client is configured as a supernode. If you previously relied on calldata for data availability, switch to blob-based retrieval. See the [Blob Storage](/operate/operators/setup/blob_storage.md) guide for configuration details.

### Withdrawal delay increase

The governance execution delay has increased from 7 days to 30 days. This extends the time required for staker withdrawals from approximately 15 days to approximately 38 days.

**Migration**: No configuration changes needed. Be aware that withdrawal processing will take longer after the upgrade.

### Prover architecture change

The prover now runs as a node subsystem rather than a separate standalone process. Start it alongside your node using the `--prover-node` flag:

```bash
aztec start --node --prover-node
```

**Migration**: If you were running the prover as a separate process, update your deployment to run it as part of the node with `--prover-node`.

## Removed features

## New features

### Initial ETH per fee asset configuration

A new environment variable `AZTEC_INITIAL_ETH_PER_FEE_ASSET` has been added to configure the initial exchange rate between ETH and the fee asset (AZTEC) at contract deployment. This value uses 1e12 precision.

**Default**: `10000000` (0.00001 ETH per AZTEC)

**Configuration:**

```bash
--initialEthPerFeeAsset <value>       ($AZTEC_INITIAL_ETH_PER_FEE_ASSET)
```

This replaces the previous hardcoded default and allows network operators to set the starting price point for the fee asset.

### `reloadKeystore` admin RPC endpoint

Node operators can now update validator attester keys, coinbase, and fee recipient without restarting the node by calling the new `reloadKeystore` admin RPC endpoint.

What is updated on reload:

* Validator attester keys (add, remove, or replace)
* Coinbase and fee recipient per validator
* Publisher-to-validator mapping

What is NOT updated (requires restart):

* L1 publisher signers
* Prover keys
* HA signer connections

New validators must use a publisher key already initialized at startup. Reload is rejected with a clear error if validation fails.

### Admin API key authentication

The admin JSON-RPC endpoint now supports auto-generated API key authentication.

**Behavior:**

* A cryptographically secure API key is auto-generated at first startup and displayed once via stdout
* Only the SHA-256 hash is persisted to `<dataDirectory>/admin/api_key_hash`
* The key is reused across restarts when `--data-directory` is set
* Supports both `x-api-key` and `Authorization: Bearer <key>` headers
* Health check endpoint (`GET /status`) is excluded from auth (for k8s probes)

**Configuration:**

```bash
--admin-api-key-hash <hex>                 ($AZTEC_ADMIN_API_KEY_HASH)    # Use a pre-generated SHA-256 key hash
--disable-admin-api-key                    ($AZTEC_DISABLE_ADMIN_API_KEY) # Disable auth entirely
--reset-admin-api-key                      ($AZTEC_RESET_ADMIN_API_KEY)   # Force key regeneration
```

**Helm charts**: Admin API key auth is disabled by default (`disableAdminApiKey: true`). Set to `false` in production values to enable.

**Migration**: No action required — auth is opt-out. To enable, ensure `--disable-admin-api-key` is not set and note the key printed at startup.

### Transaction pool error codes for RPC callers

Transaction submission via RPC now returns structured rejection codes when a transaction is rejected by the mempool:

* `LOW_PRIORITY_FEE` — tx priority fee is too low
* `INSUFFICIENT_FEE_PAYER_BALANCE` — fee payer doesn't have enough balance
* `NULLIFIER_CONFLICT` — conflicting nullifier already in pool

**Impact**: Improved developer experience — callers can now programmatically handle specific rejection reasons.

### RPC transaction replacement price bump

Transactions submitted via RPC that clash on nullifiers with existing pool transactions must now pay at least X% more in priority fee to replace them. The same bump applies when the pool is full and the incoming tx needs to evict the lowest-priority tx. P2P gossip behavior is unchanged.

**Configuration:**

```bash
P2P_RPC_PRICE_BUMP_PERCENTAGE=10     # default: 10 (percent)
```

Set to `0` to disable the percentage-based bump (still requires strictly higher fee).

### Validator-specific block limits

Validators can now enforce per-block and per-checkpoint limits independently from the sequencer (proposer) limits. This allows operators to accept proposals that exceed their own proposer settings, or to reject proposals that are too large even if the proposer's limits allow them.

**Configuration:**

```bash
VALIDATOR_MAX_L2_BLOCK_GAS=<value>         # Max L2 gas per block for validation
VALIDATOR_MAX_DA_BLOCK_GAS=<value>         # Max DA gas per block for validation
VALIDATOR_MAX_TX_PER_BLOCK=<value>         # Max txs per block for validation
VALIDATOR_MAX_TX_PER_CHECKPOINT=<value>    # Max txs per checkpoint for validation
```

When not set, no per-block limit is enforced for that dimension — only checkpoint-level protocol limits apply. These do not fall back to the `SEQ_` values.

### Setup allow list extendable via network config

The setup phase allow list can now be extended via the network configuration JSON (`txPublicSetupAllowListExtend` field). This allows network operators to distribute additional allowed setup functions to all nodes without requiring code changes. The local environment variable takes precedence over the network-json value.

## Changed defaults

## Troubleshooting

## Next steps

* [How to Run a Sequencer Node](/operate/operators/setup/sequencer_management.md) - Updated setup instructions
* [Advanced Keystore Usage](/operate/operators/keystore.md) - Keystore configuration
* [Ethereum RPC Calls Reference](/operate/operators/reference/ethereum_rpc_reference.md) - Infrastructure requirements
* [Aztec Discord](https://discord.gg/aztec) - Upgrade support
