UltraDAG’s checkpoint fast-sync mechanism allows new nodes to join the network without replaying the entire transaction history from genesis. Instead of processing thousands of rounds, a fresh node downloads a recent state snapshot — a checkpoint — verified by a quorum of validator co-signatures. This reduces sync time from hours to seconds.
But there was a problem. A critical one.
The Vulnerability
A fresh node with no prior knowledge of the network accepted checkpoint state from the first peer it connected to. That peer could supply an arbitrary validator set and state root. The node had no way to verify the checkpoint was legitimate because it had no anchor to compare against.
This is the classic Trust-On-First-Use (TOFU) problem. The first contact defines reality. If that first contact is malicious, the node builds its entire worldview on a lie.
In concrete terms: an attacker could spin up a node, connect to a fresh victim node before any honest peer did, and feed it a checkpoint with a forged validator set controlled entirely by the attacker. The victim would accept it, apply the state, and from that point forward operate on a completely fabricated chain. No amount of honest peers connecting later could fix this — the damage was done at first contact.
How We Found It
During a structured consensus review of the codebase, the reviewer flagged the checkpoint bootstrap path as a mainnet blocker. The question was simple: “What prevents a malicious peer from feeding false checkpoint data to a new node?”
The answer was: nothing.
The checkpoint had validator signatures, yes. But those signatures only proved that some set of validators signed it. A new node had no way to know if those validators were the legitimate ones or a fabricated set created by an attacker.
The Fix
We implemented a two-part solution that chains checkpoints back to genesis and anchors the entire history to a hardcoded constant.
Part 1: Checkpoint Chain
We added a prev_checkpoint_hash field to the Checkpoint struct. Each checkpoint now includes the blake3 hash of the previous checkpoint, forming an immutable chain back to genesis:
pub struct Checkpoint {
pub round: u64,
pub state_root: [u8; 32],
pub validator_set_hash: [u8; 32],
pub prev_checkpoint_hash: [u8; 32], // Added
pub signatures: Vec<Signature>,
}
This means you can’t forge a single checkpoint in isolation. To create a fake checkpoint at round 10,000, you’d need to forge the entire chain of 100 checkpoints (assuming checkpoints every 100 rounds) back to genesis. Each hash depends on the previous, so breaking one link breaks the entire chain.
Part 2: Genesis Anchor
The checkpoint chain alone isn’t enough. An attacker could still create a complete forged chain starting from a fake genesis. We need an anchor — a known-good starting point.
We added GENESIS_CHECKPOINT_HASH, a constant hardcoded into every binary. It’s the blake3 hash of the genesis state, computed deterministically from the initial validator set and zero balances:
pub const GENESIS_CHECKPOINT_HASH: [u8; 32] = [
0x8f, 0x43, 0x7e, 0x9a, 0x2c, 0x15, 0xb8, 0x6d,
0x4a, 0x91, 0x3f, 0x72, 0xe5, 0xc8, 0x0b, 0x94,
0x1d, 0x6a, 0x47, 0x23, 0x8e, 0x5c, 0x9f, 0x31,
0x7b, 0xa4, 0x68, 0x2e, 0xd1, 0x95, 0x3a, 0xf6,
];
During fast-sync, the receiving node walks the checkpoint chain backward using prev_checkpoint_hash until it reaches the genesis checkpoint (round 0). It then verifies that the genesis checkpoint’s hash matches GENESIS_CHECKPOINT_HASH.
If the hashes match, the entire chain is valid. If they don’t match, the checkpoint is rejected, and the node tries a different peer.
Key insight: A forged checkpoint must break the hash chain to succeed, which is cryptographically infeasible. The attacker would need to find a preimage for the genesis hash or break blake3 — both considered computationally impossible.
What This Means
A new node joining the network now has the same trust guarantee as a node that has been running since genesis. The genesis hash is the anchor. No peer can feed a false history without breaking the chain, and breaking the chain requires breaking the hash function.
The TOFU problem is eliminated. First contact no longer defines reality — the hardcoded genesis hash does.
Lesson Learned
Checkpoint bootstrap paths deserve the same scrutiny as the consensus path itself. New nodes are uniquely vulnerable because they have no local state to compare against. Any system that accepts state from untrusted peers on first contact should have a hardcoded anchor.
In our case, that anchor is the genesis checkpoint hash. It’s 32 bytes that prevent an entire class of attacks.
Timeline
The vulnerability was discovered and fixed in the same review session. No mainnet exposure — this was caught during testnet development. No real funds were at risk.
The fix has been deployed to testnet and will be part of the mainnet launch. Every node binary now ships with the genesis checkpoint hash baked in.
Fast-sync is now safe for production.