When you run Dolos (or any Cardano node) from a fresh database, it takes hours to reach the live chain tip. Before your code submits transactions or starts reading fresh blocks, you want to confirm the node is actually caught up. This lesson shows you two ways to check, both from the starter-kit, and explains when each is the right answer.
Two Questions, Two Tools
"Has my node finished syncing?" splits into two slightly different questions:
Question
Tool
Mini-protocol
"What slot does the node think is the tip?"
cmd/chain-tip
ChainSync GetCurrentTip
"What slot, era, epoch, and block number is the tip?"
cmd/state-query tip
LocalStateQuery
chain-tip is the cheapest way to ask "are you still moving?" state-query tip gives you richer structured data in the same round-trip and is what you'd use in an application's health-check endpoint.
Both use Node-to-Client over the Unix socket you set up in 101.1.
Prerequisites
- Completed 101.1 (starter-kit cloned,
CARDANO_NODE_SOCKET_PATHandCARDANO_NODE_MAGICexported) - Dolos running in the background
Approach 1: chain-tip
You already ran this in 101.1. One slot number, one block hash, exits.
go run ./cmd/chain-tip
Chain Tip:
Slot: 56123456 Block Hash: e3f1a2...
The implementation is just:
tip, err := o.ChainSync().Client.GetCurrentTip()
// tip is ocommon.Tip{ Point: { Slot uint64; Hash []byte }, BlockNumber uint64 }
fmt.Printf("Chain Tip:\nSlot: %-10d Block Hash: %x\n", tip.Point.Slot, tip.Point.Hash)
When you'd use this in real code: before streaming with chain-sync, to pick a sensible starting point. Or inside a liveness check that only needs to confirm the node is responding.
Approach 2: state-query tip
A richer view, accessed via LocalStateQuery. From the starter-kit:
go run ./cmd/state-query tip
Output:
Era: Conway (7)
Epoch: 432
Block Number: 2834721
Slot Number: 56123456
Block Hash: e3f1a2...
The program calls multiple queries in sequence:
// inside state-query/main.go
era, _ := o.LocalStateQuery().Client.GetCurrentEra()
tip, _ := o.ChainSync().Client.GetCurrentTip()
epochNo, _ := o.LocalStateQuery().Client.GetEpochNo()
// ...
The state-query command also accepts other subcommands — protocol-params, stake-distribution, utxos-by-address, etc. See go run ./cmd/state-query --help for the full list. You'll use several of these in Modules 202 and 301.
Confirming Dolos Is Caught Up
Run both commands, then compare to a public source:
# Our view (via Dolos)
go run ./cmd/state-query tip
# Public view
curl -s https://preprod.cardanoscan.io/ | grep -o 'Slot [0-9]*' | head -1
# or visit https://preprod.cardanoscan.io/ in the browser
If the two slot numbers are within a few blocks of each other, Dolos is synced. If yours is thousands of slots behind, Dolos is still catching up — leave dolos daemon running and re-check in a few minutes.
A Quick Watch Loop
while true; do
go run ./cmd/chain-tip
sleep 10
done
The slot should advance by about 20 each iteration on preprod (one slot per second, ~one block every ~20 slots).
Two Things Worth Knowing
- Tip moves even when synced. A synced node is not frozen — it's producing new tips every slot. "Synced" means "tracking the live chain at the same pace as everyone else," not "stopped."
- Syncing vs. caught up. During initial sync, the slot number in the tip rises as fast as the network can deliver blocks — much faster than wall-clock. Once caught up, the slot number advances in line with real time.
Common Issues
Slot is a long way behind wall-clock
Dolos is still catching up. Watch the dolos daemon log — you should see it replaying blocks. Initial sync from Mithril snapshot is faster than syncing from genesis but can still take 15–30 minutes on preprod.
state-query fails with unsupported query or similar
Some LocalStateQuery queries need a fully-synced node or only work on certain eras. Tip queries work across all eras. If you hit this on a specific subcommand, check the gOuroboros feature matrix in its README.
Slot prints 0
Node is up but hasn't intersected the chain yet — very early in startup. Wait 10–20 seconds and retry.
You'll Know You're Successful When
chain-tipandstate-query tipboth return a slot close to the current preprod slot on Cardanoscan- The slot advances between runs
- You understand which command you'd use for a quick liveness ping vs. a structured status report
Practice Tasks
- Run both commands and note the wall-clock time between completing each. Which is faster and why?
- Stop Dolos (
Ctrl+Cin its terminal), then runchain-tip. Observe the error. Restart Dolos and re-run. - Run
go run ./cmd/state-query --helpand identify two other queries you'd want for a production health dashboard.
What's Next
- 101.4 — look at pending transactions in the mempool
- 102.4 — submit a transaction back into this same node you've been querying