Purpose and Scope
This document describes the block and header structure, encoding formats, hash calculation, Merkle root construction, and WBFT-specific Extra data structures used in the StableNet blockchain.It focuses on how blocks are composed and validated, and what data is included in the header during the consensus process. Related documents:
- Transaction data structures: Transaction Types and Encoding
- Block validation and chain insertion: Blockchain Management
- Block production process: Block Production
Block Structure Overview
A block consists of a header containing metadata, a body containing transactions, and optional withdrawals and uncles lists.In StableNet (WBFT-based), uncles are not used and are always empty.
Block Type
Key fields of theBlock structure (core/types/block.go):
| Field | Type | Description |
|---|---|---|
header | *Header | Block header containing metadata and Merkle roots |
transactions | Transactions | List of transactions included in the block |
uncles | []*Header | Uncle block headers (not used) |
withdrawals | Withdrawals | Withdrawals list (optional after Shanghai) |
hash | atomic.Value | Cached block hash |
size | atomic.Value | Cached RLP-encoded size |
Internal data is copied during construction, and cached hash and size values never change afterward.
Header Structure
TheHeader is the core metadata of a block and contains cryptographic commitments to the block contents and execution results.
Core Header Fields
| Field | Type | Description |
|---|---|---|
ParentHash | common.Hash | Parent block header hash |
UncleHash | common.Hash | Uncle list hash (EmptyUncleHash in StableNet) |
Coinbase | common.Address | Block fee recipient address (validator address) |
Root | common.Hash | State trie root after block execution |
TxHash | common.Hash | Transaction Merkle root |
ReceiptHash | common.Hash | Receipt Merkle root |
Bloom | Bloom | Log bloom filter |
Difficulty | *big.Int | Block difficulty (WBFT: always 1) |
Number | *big.Int | Block number |
GasLimit | uint64 | Block gas limit |
GasUsed | uint64 | Total gas used |
Time | uint64 | Block timestamp |
Extra | []byte | WBFT consensus data (RLP-encoded) |
MixDigest | common.Hash | PoW field (unused in WBFT) |
Nonce | BlockNonce | PoW field (unused in WBFT) |
Difficultyis set to 1 to identify WBFT blocksCoinbaseis the validator’s consensus signing address and may differ from the operator addressExtracontains WBFT round data, aggregated signatures, gas tip, and epoch informationGasLimitis operated as a fixed value defined by chain parameters
Fork-Specific Optional Fields
The following fields exist only after specific forks and are included in RLP encoding only when non-nil.| Field | EIP | Fork | Description |
|---|---|---|---|
BaseFee | EIP-1559 | London | Block base fee |
WithdrawalsHash | EIP-4895 | Shanghai | Withdrawals Merkle root |
BlobGasUsed | EIP-4844 | Cancun | Blob gas usage |
ExcessBlobGas | EIP-4844 | Cancun | Excess blob gas |
ParentBeaconRoot | EIP-4788 | Cancun | Beacon chain parent root |
Body Structure
The block body contains executable data:- Transactions: Transaction list
- Uncles: Uncle headers (not used)
- Withdrawals: Withdrawals list (after the relevant fork)
RLP Encoding
Both blocks and headers use Recursive Length Prefix (RLP) encoding.Block Encoding
A block is encoded as the following RLP list:withdrawals element is omitted.
Header Encoding
Headers are RLP-encoded in the defined field order.Optional fields are included only when present.
Block and Header Hashing
Standard Hashing
The block hash is calculated only from the header.WBFT-Specific Header Hashing
In WBFT, consensus signatures are included in theExtra field.Therefore, signatures must be excluded from the hash used for signing. This is handled by
WBFTFilteredHeader():
- Removes
PreparedSealandCommittedSeal - Preserves round number, epoch info, and gas tip
- Applied only when
Difficulty == 1
Round-Dependent Hashes
During WBFT consensus rounds, a round-specific hash is used.Even for the same block proposal, different rounds result in different signing hashes.
WBFT Extra Data Structure
WBFT consensus data is stored in the header’sExtra field as RLP-encoded data.
WBFTExtra Structure
| Field | Type | Description |
|---|---|---|
VanityData | []byte | Vanity data |
RandaoReveal | []byte | BLS signature for randomness |
PrevRound | uint32 | Previous consensus round |
PrevPreparedSeal | *WBFTAggregatedSeal | Previous prepare aggregated seal |
PrevCommittedSeal | *WBFTAggregatedSeal | Previous commit aggregated seal |
Round | uint32 | Current consensus round |
PreparedSeal | *WBFTAggregatedSeal | Current prepare aggregated seal |
CommittedSeal | *WBFTAggregatedSeal | Current commit aggregated seal |
GasTip | *big.Int | Governance-defined gas tip |
EpochInfo | *EpochInfo | Next epoch info (epoch blocks only) |
WBFTAggregatedSeal
Represents a BLS-aggregated signature from multiple validators.| Field | Type | Description |
|---|---|---|
Sealers | SealerSet | Bitmap of signing validators |
Signature | []byte | Aggregated BLS signature |
EpochInfo
Included only in epoch blocks and defines the validator set for the next epoch.| Field | Type | Description |
|---|---|---|
Candidates | []*Candidate | All validator candidates |
Validators | []uint32 | Active validator indices |
BLSPublicKeys | [][]byte | Validator BLS public keys |
Merkle Root Calculation
TxHash
Calculated by building a Merkle Patricia Trie from the transaction list.An empty list uses
EmptyTxsHash.
ReceiptHash
Calculated in the same way from the receipt list.The bloom filter is derived from receipts.
UncleHash
The hash of the uncle header list.In StableNet, this is always
EmptyUncleHash.
WithdrawalsHash
Calculated from the withdrawals list in post-Shanghai blocks.Block Construction
NewBlock Function
NewBlock() constructs a block using the following steps:
- Copy the header
- Compute the transaction Merkle root
- Compute the receipt root and bloom
- Compute the uncle hash
- Assemble the body data
Difficulty = 1Extracontains the encodedWBFTExtraEpochInfois included only in epoch blocks
NewBlockWithWithdrawals() is used.
Header Sanity Checks
Header.SanityCheck() prevents DoS attacks caused by malformed inputs.
| Field | Constraint |
|---|---|
Number | 64-bit range |
Difficulty | Reasonable bit length |
Extra | Maximum size limit |
BaseFee | uint256 range |
Block Size Calculation
The block size is the total RLP-encoded size and can be queried viaBlock.Size().If blob transactions are included, sidecar data is also counted toward the size.

