BLOCKCHAIN STORAGE
Storage System
A content-addressed, two-tier storage system where every expression is identified by its BLAKE3 hash. Hot storage keeps data in memory; cold storage persists to disk. Nodes automatically advertise what they hold and request what they need.
Content-Addressed Storage
- Every expression is stored and retrieved by its 32-byte BLAKE3 hash. The hash is the address.
- Expressions form a DAG: a link pair can reference sub-expressions by hash pointer rather than embedding them inline. This enables lazy resolution.
- The storage layer is content-agnostic — it stores raw expression bytes regardless of whether they represent a block, transaction, account state, or application data.
Hot Storage (In-Memory)
- An in-memory cache for frequently accessed expressions. Implemented as a dictionary keyed by expression hash.
- Size limit — configurable via
hot_storage_limit(default 1 GiB). When the limit is exceeded, least-recently-used entries are evicted. - Newly created expressions (blocks, transactions) are written to hot storage first. They are later flushed to cold storage.
- Storage advertisements are generated from hot storage contents.
Cold Storage (On-Disk)
- Persistent on-disk storage for long-term data retention. Configured via
cold_storage_path(directory) andcold_storage_limit(default 10 GiB). - Level-based rollup — data is organized into levels (
level_0). Each level has a configurable base unit size (cold_storage_scale: KB, MB, or GB). When a level exceeds its threshold, it merges into the next level. - Expressions are serialized to binary and written to level files. An index maps expression hashes to file offsets for O(1) retrieval.
- Cold storage is initialized on node startup via
setup_storage.
Storage Advertisements
- Nodes periodically announce which expressions they hold via storage advertisements broadcast to peers.
- An advertisement contains a list of expression hashes the node can serve.
- A background thread (
advertise_storage) runs at a configurable interval (storage_index_interval, default 600 s / 10 min) to scan local storage and broadcast advertisements. - Expressions can also be advertised immediately via
node.add_expr_advertisement(expr_hash)ornode.add_expr_advertisements(expr_hashes).
Storage Requests and Retrieval
- When a node needs an expression it doesn't have, it broadcasts a
STORAGE_REQUESTmessage containing the expression hash and an offered payment. - Peers that hold the expression respond with a
STORAGE_RESPONSEcontaining the serialized expression data. - Request tracking — the node maintains a queue of pending requests (
node.expr_requests) and a deduplication set (node.add_expr_req/node.has_expr_req). - Retries — if a request isn't fulfilled, it is retried up to
storage_fetch_retriestimes (default 8) at intervals ofstorage_fetch_interval(default 0.25 s).
Storage Pricing
- Storage retrieval uses a fair-use model. Nodes serve data for free up to
fair_use_limit(default 1 MiB) per peer. - Beyond the free limit, service continues at no cost as long as the peer's download/upload ratio stays at or above
fair_use_ratio(default 0.5). Peers that share data back adequately are never asked to pay. - Payment is only requested when a peer exceeds both thresholds. The required price adjusts dynamically based on inbound request pressure (
storage_request_current_price, recalculated everystorage_request_price_intervalseconds). - Higher request volume drives the price up; lower volume lets it decay. A floor is enforced via
storage_request_minimum_price(default 1).
Storage Contracts
- When expressions are created on-chain (e.g., via
acc.putor contract deployment), a storage contract is generated. - The contract records the expression hash, the account that owns it, and a slot allocation in the storage radix trie.
- Contracts are stored in the special storage account (
0x0000...00). Each contract is an expression with slots that can be claimed by storage providers. - Claiming — a background thread (
claim_storage) monitors pending storage contracts and claims slots for the local node, earning storage fees over time. - Claim spacing — claims are deduplicated by era to prevent double-claiming.
Storage Providers
- Any node can be a storage provider by holding expressions and advertising them. Providers earn fees when they fulfill storage requests.
- The node tracks known providers and their advertised expressions. Provider information is shared via the P2P routing layer.
- Storage fees collected from on-chain operations (
acc.put,tx.log, etc.) are distributed to providers who hold the corresponding storage contracts.
Configuration Reference
| Config Key | Default | Description |
|---|---|---|
hot_storage_limit | 1 GiB | Maximum in-memory cache size in bytes |
cold_storage_limit | 10 GiB | Maximum on-disk storage size in bytes |
cold_storage_scale | MB | Base unit for level rollup: KB, MB, or GB |
cold_storage_path | auto | Directory for cold storage files (auto: data directory) |
storage_index_interval | 600 s | Seconds between storage advertisement scans |
storage_request_minimum_price | 1 | Minimum price to accept for a storage request |
storage_request_price_interval | 5.0 s | Seconds between price recalculation cycles |
storage_fetch_interval | 0.25 s | Seconds between storage request retries |
storage_fetch_retries | 8 | Maximum number of fetch retries per request |
