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

# Ancient Store and Data Lifecycle

## Purpose and Scope

This document describes the ancient store subsystem (commonly referred to as the “freezer”) in go-stablenet and how it manages the storage lifecycle of historical blockchain data.

The ancient store is an **append-only archive storage layer** that separates and preserves old block data in order to optimize performance and disk usage of the active database.

This page covers:

* Ancient store architecture and its separation of roles from the active database
* Data migration flow from the active store to the ancient store
* Ancient store operations (read, write, truncate)
* Chain rewind handling when frozen data exists
* Importing and exporting historical data using the Era1 format

For the active database layer and trie storage, see [Database Layer and Merkle Patricia Trie](/en/storage-architecture/9.1-database-layer-and-merkle-patricia-tries).\
For caching and snapshots, see [Caching and Snapshots](/en/storage-architecture/9.2-caching-and-snapshots).

## Ancient Store Architecture

The ancient store is a dedicated storage for historical blockchain data that has become **immutable**.\
This layer is designed to improve performance and disk efficiency with the following characteristics:

* Append-only write model
* Sequential access by block number
* Physical and logical separation from the active key-value database
* Minimized random-access cost for old data

### Storage Layers

Blockchain data is divided into two main layers:

* **Active Database**\
  Recent blocks, state (tries), headers, transaction indices, and other data\
  that require frequent random access and writes
* **Ancient Store**\
  Blocks, receipts, and total difficulty data that are sufficiently old and no longer mutable

### Database Interface

The `ethdb.Database` interface provides a unified access point for both the active and ancient stores:

| Method                       | Description                          | Storage Layer   |
| ---------------------------- | ------------------------------------ | --------------- |
| `Ancients()`                 | Returns the number of frozen blocks  | Ancient store   |
| `TruncateHead(n)`            | Removes ancient data after block `n` | Ancient store   |
| `Get(key)` / `Put(key, val)` | Key-value read/write                 | Active database |
| `NewBatch()`                 | Create a batch write                 | Active database |

Although accessed via the same DB handle, the ancient store uses a separate internal implementation optimized for **sequential, immutable data**.

## Data Lifecycle and Migration

### Block Data States

Blockchain data transitions through the following stages depending on block age and state availability:

1. **Active State**\
   Recent blocks that must support state (trie) access and rewinds
2. **Transitional State**\
   State is no longer needed, but data has not yet moved to the ancient store
3. **Frozen State**\
   State access is no longer required; data is considered immutable and stored in the ancient store

### Freezer Threshold

The freezer threshold defines the point at which blocks are migrated to the ancient store.\
Blocks below this threshold are considered **ineligible for state recovery during rewinds**.

Key considerations:

* **State availability**\
  Blocks requiring state (tries) must remain in the active database
* **`TriesInMemory` constant**\
  Typically, the most recent \~128 blocks are kept in the active DB
* **Snap synchronization**\
  During snap sync, the pivot block may affect the freezer boundary
* **Full synchronization**\
  Once state is no longer required, old blocks are migrated sequentially

## Ancient Store Operations

### Reading Ancient Data

When accessing old blocks, the BlockChain logic transparently reads data from the ancient store.

From the perspective of higher layers, there is no need to explicitly distinguish whether data resides in the active DB or the ancient store.

### Writing and Truncation

Modifications to the ancient store occur only in limited scenarios:

1. **Chain rewind (`SetHead`)**\
   When rewinding below the frozen threshold
2. **Historical data import**\
   When injecting past data via Era1 archives

`TruncateHead` removes data **after a given block number** from the ancient store.

## Chain Rewind with Ancient Data

### Rewind Process

When rewinding the chain (`SetHead`, `SetHeadWithTimestamp`),\
special handling is required for frozen data.

| Scenario                       | Active DB Action             | Ancient Store Action    |
| ------------------------------ | ---------------------------- | ----------------------- |
| Target above freezer threshold | Delete active blocks/headers | None                    |
| Target below freezer threshold | Delete all active blocks     | Truncate ancient store  |
| Rewind to genesis              | Reset active DB              | Remove all ancient data |

This logic is implemented in the `setHeadBeyondRoot` flow.

### Handling Missing State

During rewind, the system must locate a block **with available state**:

1. Check `HasState(root)` or `stateRecoverable(root)`
2. If state is missing, move to the parent block
3. Rewinds below the snap pivot are prohibited
4. If recoverable, attempt `triedb.Recover(root)`

### Safety of Ancient Truncation

Ancient truncation follows strict safety rules:

* Executed via a single `TruncateHead` call
* Active DB cleanup performed first
* Hash/number mappings of removed blocks deleted
* Chain head markers updated atomically

## Importing and Exporting Historical Data

### Era1 Archive Format

go-stablenet uses the Era1 format to bundle historical blockchain data.

| Component        | Content               | Purpose                       |
| ---------------- | --------------------- | ----------------------------- |
| Era Archive      | \~8192 blocks         | Sequential storage unit       |
| Block Data       | Header, Body, Tx      | Block reconstruction          |
| Receipts         | Transaction receipts  | Execution result verification |
| Total Difficulty | Cumulative difficulty | Chain weight calculation      |
| Root Hash        | Era Merkle root       | Integrity verification        |

### Import Process

`ImportHistory` writes Era1 archives **directly into the ancient store**.\
Since the active DB is bypassed, this enables fast bootstrapping.

### Export Process

`ExportHistory` packages existing chain data into the Era1 format for external storage or distribution.

### Direct Ancient Store Initialization

When attaching an external ancient store to an empty node, automatic initialization is performed at startup.

This is useful for:

* Fast initialization from a trusted archive
* Physical separation of ancient and active data
* Disaster recovery setups

## Integration with BlockChain

### BlockChain Structure Fields

```text theme={null}
type BlockChain struct {
	db ethdb.Database
	triedb *triedb.Database
	stateCache state.Database
	currentBlock atomic.Pointer[types.Header]
	currentSnapBlock atomic.Pointer[types.Header]
	bodyCache *lru.Cache[common.Hash, *types.Body]
	receiptsCache *lru.Cache[common.Hash, []*types.Receipt]
	blockCache *lru.Cache[common.Hash, *types.Block]
}
```

### Ancient Store Query Patterns

| Operation                | Implementation               | Ancient Check |
| ------------------------ | ---------------------------- | ------------- |
| Get block by number      | Branch on `Ancients()`       | Yes           |
| Header lookup            | Active → ancient fallback    | Implicit      |
| Chain continuity check   | Verify ancient boundary      | Yes           |
| State availability check | Ancient blocks have no state | Yes           |

### Interaction with Snap Synchronization

* Snap pivot block may lie at the ancient boundary
* Receipt chains are filled via `InsertReceiptChain`
* `currentSnapBlock` and `currentBlock` may diverge
* Snap insertion below the boundary is prohibited

## Maintenance Operations

### Disk Space Management

Because the ancient store can occupy a large portion of disk space, block count and disk usage should be continuously monitored.

### Database Corruption Recovery

Possible causes:

* Abnormal shutdown during truncation
* Filesystem errors
* Manual file modification

Recovery procedure:

1. Verify ancient count and head at startup
2. Automatically truncate on mismatch
3. Manually recover using `SetHead` if necessary

## Best Practices

### Operational Guidelines

1. The ancient store can be backed up while running
2. Consider placing it on a separate disk for I/O isolation
3. Monitor ancient block count and disk usage separately
4. Ancient data is immutable and removed only via truncation

### Performance Considerations

| Aspect           | Recommendation                               | Rationale                       |
| ---------------- | -------------------------------------------- | ------------------------------- |
| Ancient location | Disk with strong sequential read performance | Append-only access pattern      |
| Active DB        | Disk with strong random I/O performance      | Frequent reads/writes           |
| Memory           | Minimal caching                              | Low access frequency            |
| Synchronization  | Full sync fills naturally                    | Snap requires separate receipts |
