tenzro-storage 0.1.0

State storage layer for Tenzro Network — Merkle trees, RocksDB, block storage, snapshots
Documentation

tenzro-storage

State storage layer for Tenzro Network. Provides persistent storage for Tenzro Ledger (the L1 settlement layer).

Overview

The tenzro-storage crate provides a comprehensive storage infrastructure for the Tenzro Network blockchain, including efficient key-value storage, Merkle Patricia Trie state commitment, block indexing, account management, and state snapshots.

Features

  • RocksDB Integration: High-performance persistent storage with 30 column families
  • KvStore trait: get, put, delete, get_keys_with_prefix, write_batch, write_batch_sync — used by upper-layer registries for write-through persistence and startup hydration
  • Merkle Patricia Trie: Efficient state commitment and cryptographic proof generation
  • Block Storage: Fast indexing and retrieval of blocks by hash and height
  • Account Storage: Comprehensive account state management with balance and nonce tracking
  • State Snapshots: Point-in-time state snapshots with automatic pruning and compression
  • In-Memory Storage: Testing-friendly in-memory storage implementation
  • Durability Guarantees: Explicit fsync via write_batch_sync() for finalized blocks
  • Async/Await Support: Full async interface for all storage operations

Architecture

Column Families (28 total)

The storage layer uses RocksDB with the following column families:

  • blocks - Block data indexed by hash and height
  • state - Merkle Patricia Trie state data
  • accounts - Account state and metadata
  • transactions - Transaction storage and indexing
  • metadata - System metadata and configuration
  • snapshots - State snapshots at specific heights
  • identities - TDIP identity registry
  • delegations - Identity delegation records
  • credentials - Verifiable credentials
  • channels - Micropayment channels
  • agents - AI agent registry and state
  • models - Model catalog and metadata
  • providers - Provider registrations
  • tasks - Task marketplace data
  • agent_templates - Agent template definitions
  • skills - Skill registry
  • tools - Tool definitions
  • tokens - Token registry (ERC-20, SPL, CIP-56)
  • settlements - Settlement receipts and history
  • model_services - Served model endpoints
  • nfts - NFT metadata and ownership
  • events - Event store for event sourcing
  • webhooks - Webhook subscriptions
  • compliance - Compliance and audit logs
  • training_runs - Tenzro Train run metadata
  • training_receipts - Tenzro Train commitment receipts
  • audit - Audit log records
  • approvals - Approval state for multi-step flows

Data Availability Primitives (da module)

High-volume receipts (inference, agent message, channel updates) ship a commitment + pointer instead of the full payload; sensitive low-volume receipts (kill-switch, governance, escrow, lifecycle) stay inline.

  • ReceiptEnvelope { kind, storage_mode, inline_summary, inline_payload, da_pointer, commitment, mandate_ref } - Receipts either embed the payload (Inline) or record a pointer to an external DA layer (OffloadedDA). commitment is always SHA-256(canonical_payload) regardless of mode. The optional mandate_ref ties the receipt to a signed off-chain mandate (AP2 cart, x402 challenge, MPP session, Stripe SPT, Visa TAP, Mastercard Agent Pay, Capital Intent, Workflow step) closing the audit loop from intent → settlement
  • MandateRef { protocol, mandate_hash, issuer_did, mandate_uri?, expires_at } - Reference to a signed off-chain mandate authorizing the receipt; convenience constructors MandateRef::ap2_cart(hash, did) and MandateRef::x402(hash, did); attach via ReceiptEnvelope::with_mandate(mandate_ref)
  • ReceiptKind - SettlementEscrow | SettlementChannel | Inference | AgentMessage | KillSwitch | Lifecycle | Governance with per-kind default_mode()
  • DaPointer { backend, namespace, locator, commitment_kzg, attestation_root } - Reference to an external DA layer (IrohBlobs / EigenDA / Celestia / Avail)
  • DaBackendId, DaBackendStatus
  • #[async_trait] DaBackend trait - submit / fetch / verify_availability
  • InlineFallbackBackend - Safe default; refuses offload until external backends are wired behind feature flags
  • compute_commitment(payload) -> Hash - Canonical SHA-256 commitment

Merkle Patricia Trie

The Merkle Patricia Trie implementation provides:

  • Efficient Storage: Path compression using extension nodes
  • Cryptographic Commitment: SHA-256 based state root computation
  • Proof Generation: Generate and verify Merkle proofs for state inclusion
  • Node Types: Branch (16-way), Extension (path compression), and Leaf nodes

Usage

Basic Storage Setup

use tenzro_storage::{
    config::StorageConfig,
    kv::RocksDbStore,
    block_store::BlockStoreImpl,
    account_store::AccountStoreImpl,
};
use std::sync::Arc;
use std::path::PathBuf;

// Create storage configuration
let config = StorageConfig::new(PathBuf::from("./data/tenzro-db"))
    .with_cache_size(512 * 1024 * 1024)  // 512 MB cache
    .with_compression(true);

// Open RocksDB store
let kv_store = Arc::new(RocksDbStore::open(&config)?);

// Create block and account stores
let block_store = BlockStoreImpl::new(kv_store.clone())?;
let account_store = AccountStoreImpl::new(kv_store.clone());

Block Storage

use tenzro_storage::traits::BlockStore;
use tenzro_types::{Block, BlockHeight, Hash};

// Store a block
block_store.put_block(&block).await?;

// Retrieve by hash
let block = block_store.get_block(&block_hash).await?;

// Retrieve by height
let block = block_store.get_block_by_height(BlockHeight::new(100)).await?;

// Get latest block
let latest = block_store.latest_block().await?;

// Get block range
let blocks = block_store
    .blocks_by_height_range(
        BlockHeight::new(100),
        BlockHeight::new(200)
    )
    .await?;

Account Storage

use tenzro_storage::traits::AccountStore;
use tenzro_types::{Account, Address, Nonce};

// Store an account
account_store.put_account(&account).await?;

// Retrieve an account
let account = account_store.get_account(&address).await?;

// Get balance
let balance = account_store.get_balance(&address).await?;

// Update nonce
account_store.update_nonce(&address, Nonce::new(5)).await?;

// Delete account
account_store.delete_account(&address).await?;

Merkle Patricia Trie

use tenzro_storage::merkle::MerklePatriciaTrie;

let mut trie = MerklePatriciaTrie::new();

// Insert key-value pairs
trie.insert(b"key1", b"value1")?;
trie.insert(b"key2", b"value2")?;

// Commit changes and get state root
let state_root = trie.commit()?;

// Get values
let value = trie.get(b"key1")?;

// Generate Merkle proof
let proof = trie.generate_proof(b"key1")?;

// Verify proof (reconstructs root hash from proof and verifies match)
let is_valid = MerklePatriciaTrie::verify_proof(&proof, state_root, Some(b"value1"))?;

// Delete a key
trie.delete(b"key1")?;
trie.commit()?;

State Snapshots

use tenzro_storage::snapshot::{SnapshotManager, CompressionType};
use tenzro_types::{BlockHeight, Hash};

// Create snapshot manager
let snapshot_manager = SnapshotManager::new(kv_store.clone(), 100);

// Create a snapshot
let snapshot = snapshot_manager
    .create_snapshot(
        BlockHeight::new(1000),
        state_root,
        block_hash,
        state_data,
    )
    .await?;

// Load a snapshot
let snapshot = snapshot_manager.load_snapshot(BlockHeight::new(1000)).await?;

// List all snapshots
let snapshots = snapshot_manager.list_snapshots().await?;

// Get latest snapshot
let latest = snapshot_manager.latest_snapshot().await?;

// Restore from snapshot
use tenzro_storage::snapshot::SnapshotRestorer;
let restored = SnapshotRestorer::restore_from_snapshot(&snapshot).await?;

Durability and Persistence

use tenzro_storage::kv::WriteOp;

// Buffered write (may be lost on power failure)
kv_store.write_batch(vec![
    WriteOp::Put {
        cf: "accounts".to_string(),
        key: key1,
        value: value1,
    },
])?;

// Durable write with fsync (survives power failure)
kv_store.write_batch_sync(vec![
    WriteOp::Put {
        cf: "blocks".to_string(),
        key: block_hash.to_vec(),
        value: serialized_block,
    },
])?;

In-Memory Storage (Testing)

use tenzro_storage::kv::MemoryStore;

// Create in-memory store for testing
let kv_store = Arc::new(MemoryStore::new());

// Use exactly like RocksDB store
let account_store = AccountStoreImpl::new(kv_store);

Configuration

StorageConfig Options

  • db_path: Path to the database directory
  • cache_size: LRU cache size in bytes (default: 512 MB, max: 1 GB)
  • compression: Enable/disable compression (default: true)
  • max_open_files: Maximum number of open files (default: 1000)
  • write_buffer_size: Write buffer size in bytes (default: 64 MB)
  • max_write_buffer_number: Maximum write buffer count (default: 3)
  • target_file_size_base: Target SST file size (default: 64 MB)
  • enable_statistics: Enable RocksDB statistics (default: false)
  • snapshot_retention: Number of snapshots to retain (default: 100)
  • enable_wal: Enable Write-Ahead Log (default: true)

Storage Traits

StateStore

Generic state storage interface:

  • get(key) -> value
  • put(key, value)
  • delete(key)
  • state_root() -> Hash
  • commit() -> Hash
  • rollback()

BlockStore

Block storage interface:

  • get_block(hash) -> Block
  • get_block_by_height(height) -> Block
  • put_block(block)
  • latest_block() -> Block
  • blocks_by_height_range(start, end) -> Vec<Block>

AccountStore

Account storage interface:

  • get_account(address) -> Account
  • put_account(account)
  • delete_account(address)
  • get_balance(address) -> u64
  • update_nonce(address, nonce)
  • get_nonce(address) -> Nonce

Dependencies

  • rocksdb - Persistent key-value storage
  • sha2 - SHA-256 hashing for Merkle trie
  • serde, serde_json, bincode - Serialization
  • tokio - Async runtime
  • parking_lot - High-performance locks
  • async-trait - Async trait support
  • flate2 - LZ4 compression for snapshots

Test Coverage

24 unit tests + 1 doc test covering:

  • RocksDB store operations (get, put, delete, batch writes)
  • Merkle Patricia Trie insertion, deletion, proof generation/verification
  • Block storage indexing (by hash and height)
  • Account storage operations
  • Snapshot creation, compression, and restoration
  • State root computation and commitment
  • Genesis block persistence
  • Durability guarantees (write_batch_sync with fsync)

Constants

  • STORAGE_VERSION: 1
  • MAX_CACHE_SIZE: 1 GB (1,073,741,824 bytes)
  • DEFAULT_SNAPSHOT_RETENTION: 100 snapshots

License

Licensed under either of:

at your option.