Finality for applications¶
| Stage | Meaning | How to check |
|---|---|---|
| Pending | In a node's pool | eth_getTransactionByHash returns it with blockNumber: null |
| Included | In the current canonical chain; can still be reorganised by a heavier PoW branch | Receipt exists |
| BFT-finalized | At or below a checkpoint signed by > 2/3 of the epoch set's stake; nodes never reorganise below it | blockNumber ≤ g4_status.finalized_height and block hash unchanged |
Checkpoints are every 32 blocks (epochs). Finality normally trails the head by one to two epochs; in the tested run a transaction became final after about 8 minutes.
quickstart/wait-finality.sh
# Inclusion is not finality. Wait until the block is at or below the BFT-finalized checkpoint
# and still canonical (same hash). Typical delay: one to two 32-block epochs.
BLOCK=$(cast receipt "$TX" blockNumber --rpc-url "$RPC")
HASH=$(cast receipt "$TX" blockHash --rpc-url "$RPC")
for i in $(seq 1 120); do
FIN=$(cast rpc g4_status --rpc-url "$RPC" | python3 -c 'import json,sys; print(json.load(sys.stdin)["finalized_height"])')
if [ "$FIN" -ge "$BLOCK" ]; then
test "$(cast block "$BLOCK" --field hash --rpc-url "$RPC")" = "$HASH" && { echo "finalized (checkpoint $FIN)"; break; }
echo "block was reorganised out; resubmit" >&2; exit 1
fi
sleep 10
done
Rules for application developers¶
- Credit irreversible value only after BFT finality (exchanges, bridges, AI deliverables, off-chain goods).
- Re-check the block hash after finality: if your transaction's block was replaced before finalization, the transaction may be in another block or dropped.
- Do not trust a single endpoint for finality. Compare
g4_status.finalized_hashacross independent operators or run your own node. - Do not use the
safe/finalizedblock tags. On PQWERAI Core they return errors ("safe block not found","finalized block not found", measured); useg4_status. Libraries that default tofinalized(some viem/ethers helpers) must be configured to uselatestplus theg4_statuscheck. - Plan for stalls. If less than 2/3 of validator stake is online, PoW blocks continue but
finalized_heightstops advancing. Show "awaiting finality" rather than failing.
g4_status fields used for finality¶
| Field | Meaning |
|---|---|
head |
Current head height |
finalized_height, finalized_hash |
Latest BFT-finalized checkpoint |
justified_height, justified_hash |
Latest justified checkpoint (finalization candidate) |
finality |
true when the node runs the registry/finality profile |
epoch_set_size, epoch_set_root |
Validator set of the current epoch |
Full method reference: g4_status.
Sources at 72057fe3ec: testnet/release/network/network.json · core/source/cmd/pqwerai-core/g4.go · developers/examples/quickstart/wait-finality.sh
Found a problem? Report a documentation issue · Build testnet-rc1+72057fe3ec