Skip to main content
Version: dev

Start the node

Time: 5 to 15 minutes. Launch the container and wait for it to sync with the network.

1. Start the node

2. Watch the logs

docker compose logs -f aztec-sequencer

Press Ctrl+C to exit the log view. The node continues running in the background.

Initial sync

Initial sync takes 5 to 30 minutes depending on your L1 endpoint speed and current chain height. You'll see blocks being processed in the logs. Wait until the node catches up to the current proven tip.

3. Check sync progress

In a new terminal, ask the node which L2 block tips it has seen:

curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"node_getL2Tips","params":[],"id":1}' \
http://localhost:{{AZTEC_PORT}} | jq '.result | {proposed: .proposed.number, proven: .proven.block.number, finalized: .finalized.block.number}'

Expected output looks like:

{
"proposed": 75432,
"proven": 75408,
"finalized": 75392
}
  • proposed is the latest block the network is producing. As soon as your node is alive and on the right network, this number should increase every few seconds.
  • proven is the latest block with a verified ZK proof submitted to L1. Lags behind proposed by an epoch or so. This is the "fully synced" signal.
  • finalized is the latest block whose L1 finalization is also confirmed. Lags behind proven by an Ethereum epoch.

proven and finalized may show null for the first few minutes after startup, before the node has seen a proven epoch. That's normal. Re-run the command after a minute or two; the numbers should appear and start climbing.

4. Check node readiness and identity

node_isReady returns true once the node is ready to accept transactions:

curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"node_isReady","params":[],"id":1}' \
http://localhost:{{AZTEC_PORT}} | jq -r '.result'

node_getNodeInfo confirms which network and version you're on. Use it to catch "I started the node against the wrong --network" mistakes early:

curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"node_getNodeInfo","params":[],"id":1}' \
http://localhost:{{AZTEC_PORT}} | jq '.result | {nodeVersion, l1ChainId, rollupVersion, rollupAddress: .l1ContractAddresses.rollupAddress}'

Expected output looks like:

{
"nodeVersion": "4.2.0",
"l1ChainId": 1,
"rollupVersion": "...",
"rollupAddress": "0xae2001f7e21d5ecabf6234e9fdd1e76f50f74962"
}

l1ChainId: 1 is Ethereum mainnet, 11155111 is Sepolia. The rollupAddress should match the address in your track's L1 contract addresses table.

Before you continue

  • proposed is increasing every few seconds (node is alive).
  • proven is non-null and converging on proposed (node is fully synced).
  • node_isReady returns true.
  • node_getNodeInfo shows the rollup address and L1 chain id you expect.
  • Logs show no persistent errors.
Something wrong?
  • "Error connecting to Ethereum" — Check ETHEREUM_HOSTS in your .env. Test with cast block-number --rpc-url YOUR_URL.
  • Node exits immediately — Run docker compose logs aztec-sequencer (without -f) to see the exit reason. Common causes: invalid keystore path, port conflict, or Docker out of disk space.
  • Sync stuck — Your L1 endpoints may be rate-limited. Consider self-hosting Geth + Prysm or using a higher-tier provider plan.
  • P2P connection issues — Verify port forwarding with nc -zv YOUR_IP 40400. Check both TCP and UDP are forwarded.

Stuck? Ask in Discord.