> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stablenet.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Block Structure and Encoding

## 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](/en/core-architecture/3.5-transaction-types-and-encoding)
* Block validation and chain insertion: [Blockchain Management](/en/core-architecture/3.2-blockchain-management)
* Block production process: [Block Production](/en/consensus-and-block-production/4.2-block-production-and-mining)

## 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 the `Block` 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                           |

Blocks are treated as **immutable** objects after creation.\
Internal data is copied during construction, and cached hash and size values never change afterward.

## Header Structure

The `Header` 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)                      |

**StableNet specifics:**

* `Difficulty` is set to 1 to identify WBFT blocks
* `Coinbase` is the validator’s consensus signing address and may differ from the operator address
* `Extra` contains WBFT round data, aggregated signatures, gas tip, and epoch information
* `GasLimit` is 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:

```
[header, transactions, uncles, withdrawals]
```

For pre-Shanghai blocks, the `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**.

```
block_hash = keccak256(rlp(header))
```

The computed hash is cached to avoid repeated calculation.

### WBFT-Specific Header Hashing

In WBFT, consensus signatures are included in the `Extra` field.\
Therefore, **signatures must be excluded from the hash used for signing**.

This is handled by `WBFTFilteredHeader()`:

* Removes `PreparedSeal` and `CommittedSeal`
* Preserves round number, epoch info, and gas tip
* Applied only when `Difficulty == 1`

This prevents circular dependencies between signatures and hashes.

### 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’s `Extra` 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) |

Fields with nil values are excluded from RLP encoding.

### 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:

1. Copy the header
2. Compute the transaction Merkle root
3. Compute the receipt root and bloom
4. Compute the uncle hash
5. Assemble the body data

For WBFT blocks:

* `Difficulty = 1`
* `Extra` contains the encoded `WBFTExtra`
* `EpochInfo` is included only in epoch blocks

After Shanghai, `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 via `Block.Size()`.\
If blob transactions are included, sidecar data is also counted toward the size.
