State Sync & Checkpoints
State sync allows new nodes to join the network without replaying the entire block history. Instead, a joining node downloads a verified state snapshot at a recent checkpoint and replays only the blocks after that point.
Overview
Section titled “Overview”The state sync system has three layers:
- Checkpoints - periodic state commitments recorded at finalized heights
- Snapshots - exportable bundles of headers, MMR entries, and checkpoint metadata
- State streaming - a P2P protocol for downloading state entries in paginated chunks
Checkpoint creation (validator) │ ▼┌──────────────────┐ ┌──────────────────┐│ SnapshotManifest │ │ LightSnapshot ││ (full headers + │ │ (single header + ││ MMR entries + │ │ MMR proof + ││ validator sets) │ │ finality proof) │└────────┬─────────┘ └────────┬─────────┘ │ │ ▼ ▼ Full sync path Fast sync path (export/import) (P2P state streaming)Checkpoints
Section titled “Checkpoints”A checkpoint is a (height, state_root) pair recorded when a block is finalized. The state_root is a Blake3 commitment over the execution state at that height.
When checkpoints are created
Section titled “When checkpoints are created”Checkpoints are created during block finalization when the block height satisfies the configured interval:
# Configure checkpoint interval (every 1000 blocks)ashen node run --checkpoint-interval 1000When no interval is configured, checkpoints are created only during snapshot operations and state sync.
Storage
Section titled “Storage”Checkpoints are stored under data/checkpoints/ and managed through the ChainStore trait:
| Operation | Description |
|---|---|
put_state_checkpoint | Store a new checkpoint |
state_checkpoint(height) | Fetch checkpoint at a specific height |
latest_state_checkpoint | Get the most recent checkpoint |
list_checkpoints(limit) | List checkpoints ordered by height descending |
Snapshot Types
Section titled “Snapshot Types”Full Snapshot (SnapshotManifest)
Section titled “Full Snapshot (SnapshotManifest)”A full snapshot contains everything needed to bootstrap a node from genesis:
| Field | Description |
|---|---|
headers | Block headers from genesis to checkpoint (ascending order) |
mmr_entries | Finalized MMR entries corresponding to each header |
mmr_root | Expected MMR root after all entries are added |
checkpoint | Height and state root at the snapshot point |
validator_sets | Validator sets for all epochs in the range |
finality_proof | BLS threshold certificate for the checkpoint block |
Full snapshots use Borsh serialization and can be exported/imported via the export_snapshot and import_snapshot functions.
Light Snapshot (LightSnapshot)
Section titled “Light Snapshot (LightSnapshot)”A light snapshot is a minimal proof bundle for nodes that already have a trusted MMR root (e.g., from a light client):
| Field | Description |
|---|---|
checkpoint | Height and state root |
header | Block header at the checkpoint height |
mmr_proof | MMR membership proof for the checkpoint block |
finality_proof | BLS threshold certificate (optional) |
validator_set | Validator set for the checkpoint epoch |
Light snapshots are verified against a trusted MMR root rather than replaying the full header chain.
State Sync Protocol
Section titled “State Sync Protocol”New nodes download state entries over the follower sync P2P channel using a request/response protocol.
Message Types
Section titled “Message Types”| Message | Direction | Purpose |
|---|---|---|
StateCheckpointRequest | Node -> Peer | Query checkpoint metadata at a height |
StateCheckpointResponse | Peer -> Node | Returns height, state root, total entry count, block hash |
StateChunkRequest | Node -> Peer | Request a page of state entries |
StateChunkResponse | Peer -> Node | Returns state entries with pagination cursor |
Protocol Limits
Section titled “Protocol Limits”| Limit | Value |
|---|---|
| Max headers per response | 64 |
| Max finality proofs per response | 64 |
| Max state entries per chunk | 1,024 |
Sync Session
Section titled “Sync Session”The StateSyncSession manages the download lifecycle through five phases:
FetchingCheckpoint -> Downloading -> Importing -> Verifying -> Complete │ └─> FailedDownloading: state entries are fetched in chunks via StateChunkRequest with offset-based pagination. Each chunk is validated against the checkpoint height.
Importing: pending entries are written to the state backend via import_pending().
Verifying: the state root is recomputed from imported entries and compared against the checkpoint’s state_root. A mismatch aborts the sync.
Default Configuration
Section titled “Default Configuration”| Parameter | Default | Description |
|---|---|---|
chunk_size | 512 | Entries requested per chunk |
request_timeout | 30s | Timeout per chunk request |
max_concurrent_requests | 4 | Parallel chunk downloads |
retry_attempts | 3 | Retries per failed chunk |
retry_delay | 1s | Delay between retries |
Bootstrap Flow
Section titled “Bootstrap Flow”A new node joining the network follows this sequence:
1. Header Sync
Section titled “1. Header Sync”The node requests block headers from peers via HeaderRequest messages, verifying:
- Finality proofs (BLS threshold signatures) against known validator sets
- Chain continuity (each header’s
parent_hashmatches the previous header’s hash)
2. Checkpoint Discovery
Section titled “2. Checkpoint Discovery”The node queries a recent checkpoint:
StateCheckpointRequest { height: None } // latest checkpoint -> StateCheckpointResponse { height, state_root, total_entries, block_hash }For verified sync, the node fetches a light snapshot and verifies it against a trusted MMR root:
get_light_snapshot(height) -> { checkpoint, header, mmr_proof, finality_proof, validators, snapshot_bytes }3. State Download
Section titled “3. State Download”The node streams state entries in chunks:
StateChunkRequest { checkpoint_height: 5000, offset: 0, limit: 512 } -> StateChunkResponse { entries: [...], has_more: true }
StateChunkRequest { checkpoint_height: 5000, offset: 512, limit: 512 } -> StateChunkResponse { entries: [...], has_more: true }
... (continues until has_more == false)4. Verification
Section titled “4. Verification”After all entries are imported, the node recomputes the state root and verifies it matches the checkpoint. On success, the node transitions to normal operation and replays blocks from the checkpoint height to the current tip.
Snapshot Verification
Section titled “Snapshot Verification”Full Snapshot
Section titled “Full Snapshot”SnapshotManifest::verify() checks:
| Check | Description |
|---|---|
| Version | Snapshot format version must match current |
| Header chain | Each header’s parent_hash matches the prior header’s hash |
| MMR root | Recomputed root from entries matches mmr_root |
| Entry count | MMR entry count matches header count |
| Checkpoint height | Must equal the last header’s height |
| State root | Checkpoint state_root matches header state_root |
Light Snapshot
Section titled “Light Snapshot”LightSnapshot::verify(trusted_root) checks:
| Check | Description |
|---|---|
| Version | Format version must match |
| Height | Checkpoint height matches header height |
| State root | Checkpoint state_root matches header state_root |
| MMR proof | Proof verifies against the trusted MMR root |
| Block hash | MMR proof entry hash matches header hash |
Trusted Root Verification
Section titled “Trusted Root Verification”A snapshot can be verified against an externally obtained MMR root (e.g., from a light client or a known good peer):
verify_against_trusted_root(manifest, trusted_root)This runs the full structural verification plus confirms the manifest’s MMR root matches the trusted value.
RPC Endpoints
Section titled “RPC Endpoints”Checkpoint Management
Section titled “Checkpoint Management”| Method | Description |
|---|---|
get_checkpoint_list | List checkpoint heights and state roots |
get_checkpoint(height) | Get checkpoint descriptor with optional archive info |
list_checkpoints(limit) | List checkpoints with archive descriptors, newest first |
Snapshot & State Sync
Section titled “Snapshot & State Sync”| Method | Description |
|---|---|
get_light_snapshot(height) | Get minimal verified snapshot for fast sync |
get_snapshot_chunk(height, offset, limit) | Stream state entries for a checkpoint |
import_snapshot_chunk(height, state_root, entries, finalize) | Admin: import state entries for bootstrap |
Related Endpoints
Section titled “Related Endpoints”| Method | Description |
|---|---|
status | Includes latest_checkpoint in response |
finalized_history_root | Current MMR root for snapshot verification |
finalized_history_proof(height) | MMR membership proof for a finalized block |
finality_proof(height) | BLS threshold certificate for a block |
CLI Operations
Section titled “CLI Operations”Export a Snapshot
Section titled “Export a Snapshot”ashen backup export --height 5000 --output snapshot.binImport a Snapshot
Section titled “Import a Snapshot”ashen backup import --input snapshot.binVerify a Checkpoint
Section titled “Verify a Checkpoint”# Verify a block is in the finalized historyashen node verify --height 5000
# Verify against a specific RPC endpointashen node verify --height 5000 --rpc-url http://localhost:3030Operational Considerations
Section titled “Operational Considerations”Disk Usage
Section titled “Disk Usage”Checkpoints are stored under data/checkpoints/ and typically consume 10-50 MB each. See Disk Growth for sizing guidance.
Archive vs Pruning Mode
Section titled “Archive vs Pruning Mode”- Archive mode (
max_retained_heights: None): retains all historical state. Useful for RPC nodes serving historical queries. - Pruning mode (
max_retained_heights: N): retains only the most recent N heights of state. Reduces disk usage but limits which checkpoints can serve state sync requests.
Monitoring
Section titled “Monitoring”The status RPC endpoint includes latest_checkpoint with height and state root. Monitor this to confirm checkpoints are being created at the expected interval.
# Track checkpoint creationashen_latest_checkpoint_heightRelated
Section titled “Related”- Disk Growth - Storage sizing and checkpoint disk usage
- Light Clients - MMR proofs and finality verification
- Storage - State backend and Merkle tree structure
- Running a Node - Node setup and checkpoint configuration
- RPC API - Full endpoint reference