Skip to main content

Purpose and Scope

This document describes the blockchain management subsystem responsible for maintaining the canonical chain, inserting blocks, and handling chain reorganization.
It explains how BlockChain and HeaderChain track block headers, bodies, receipts, and metadata required for chain selection and state management.
Related documents:

Core Structures

BlockChain

The BlockChain type is the central component that manages the canonical blockchain.
It coordinates block insertion, validation, state execution, and chain reorganization, and works together with the consensus engine (consensus.Engine), fork choice logic (ForkChoice), state processor (Processor), and block validator (Validator).
It tracks several key heads as internal state: the current canonical head (currentBlock), the snapshot synchronization reference block (currentSnapBlock), the finalized block (currentFinalBlock), and the safe block (currentSafeBlock).
These head pointers are updated according to consensus rules and fork choice results.

HeaderChain

HeaderChain is a lightweight chain structure that manages block header storage and number–hash mappings.
It is responsible for header-level validation and chain traversal, and coordinates header chain reorganization and canonical header mapping updates.
Full block insertion is handled by BlockChain, while HeaderChain is used as a subordinate component.

Canonical Chain Management

The canonical chain represents the official chain path followed by the node. The blockchain maintains two core mappings:
  • Number → Hash: The canonical block hash for a given block number
  • Hash → Number: The block number corresponding to a given block hash
These mappings are updated consistently during chain reorganization and are used as the reference for RPC queries and internal validation.

State Loading at Initialization

During initialization, the loadLastState() method restores chain state from disk:
  1. Read the last head block hash from the database
  2. Load the head block using the hash
  3. Set the current block (currentBlock)
  4. Load the header chain head
  5. Load the snapshot reference block and finalized block

Block Insertion Pipeline

Block insertion is a multi-stage process that includes validation, execution, and canonical chain updates.

Insertion Flow Overview

The InsertChain() method is the main entry point for inserting a batch of blocks, and internally proceeds through the following stages:
Pre-check → Header validation → Body validation → State execution
→ State validation → State commit → Fork choice decision → Event publication

Stage Descriptions

1. Pre-check
  • Check the future block cache (futureBlocks)
  • Detect duplicate block insertion
  • Verify parent block existence
2. Header Validation
  • Call the consensus engine’s VerifyHeader()
  • For WBFT, verify proposer, signatures, and validator set consistency
  • Validate block number, timestamp, and gas limit rules
3. Body Validation
  • Call ValidateBody()
  • Verify transaction root hash matches the header
  • In WBFT environments, ensure that no uncle blocks are present
4. State Execution
  • Create a StateDB based on the parent block state
  • Execute each transaction via ApplyTransaction() and run the EVM
  • Accumulate receipts and gas usage
5. State Validation
  • Call ValidateState()
  • Validate gas usage, receipt bloom, and state root
6. State Commit
  • Write the block and receipts to the database
  • Commit the state trie and update snapshots
7. Fork Choice Decision
  • Evaluate the priority of the new block according to the consensus engine and fork choice rules
  • Perform chain reorganization if required
8. Event Publication
  • Emit ChainEvent and ChainHeadEvent
  • Notify logs and the transaction pool of the new head

Chain Reorganization

Chain reorganization (reorg) occurs when a chain with higher priority than the current canonical chain appears according to fork choice rules.
In StableNet’s WBFT environment, chain selection is based on consensus rules and epoch-based validator agreement rather than total difficulty.

Reorganization Process

  1. Fork choice decision: The ForkChoice logic determines whether the new block should be adopted as canonical
  2. Common ancestor discovery: Find the divergence point between the existing chain and the new chain
  3. Canonical mapping update: Update number–hash mappings via HeaderChain.Reorg()
  4. Head pointer update: Update currentBlock, currentFinalBlock, and currentSafeBlock
Key behaviors of HeaderChain.Reorg() include:
  1. Simple extension if the parent is the current head
  2. Removal of replaced canonical mappings
  3. Rewriting mappings while traversing back to the common ancestor
  4. Recording headers of the new chain as canonical
  5. Persisting the new head header hash to the database

Caching

The blockchain uses LRU caches to minimize disk access:
CacheSizePurpose
bodyCache256Block body cache
blockCache256Full block cache
receiptsCache32Transaction receipt cache
txLookupCache1024Transaction location lookup
futureBlocks256Temporary storage for future blocks

Chain Recovery

SetHead

The SetHead() method rewinds the chain to a specified block number. Typical use cases include:
  • Recovering state after corrupted blocks
  • Skipping known problematic blocks
  • Re-synchronizing after chain rule changes

Reset

Reset() removes all chain data and restores the blockchain to the genesis state.

SnapSyncCommitHead

Called after snapshot synchronization completes to set the synchronized block as the canonical head:
  1. Verify block existence
  2. Activate the state storage
  3. Validate state trie accessibility
  4. Update the current block pointer
  5. Rebuild snapshot structures

Database Schema

Block Storage Keys

Key PatternValue TypePurpose
h{num}ncommon.HashCanonical hash for a block number
h{hash}nuint64Block number for a hash
H{hash}{num}*types.HeaderBlock header
b{hash}{num}*types.BodyBlock body
r{hash}{num}[]*types.ReceiptTransaction receipts

Chain State Keys

KeyPurpose
LastBlockCanonical block head hash
LastHeaderCanonical header head hash
LastFastSnapshot reference block hash
LastFinalizedFinalized block hash
SnapshotRootSnapshot root

Error Handling

ErrorConditionHandling
ErrKnownBlockBlock already processedIgnored
ErrNoGenesisMissing genesisInitialization required
ErrBannedHashBlock hash is bannedRewind chain
ErrUnknownAncestorMissing parent blockRequest from peers
ErrPrunedAncestorParent state prunedSnapshot sync required
errInsertionInterruptedInsertion interruptedAbort current insertion