zeldhash-parser

Crates.iozeldhash-parser
lib.rszeldhash-parser
version0.5.1
created_at2025-12-13 12:39:17.966426+00
updated_at2026-01-16 22:16:53.388639+00
descriptionHigh-performance Bitcoin blockchain parser implementing the ZeldHash protocol
homepagehttps://zeldhash.com
repositoryhttps://github.com/ouziel-slama/zeldhash-parser
max_upload_size
id1982882
size299,447
Ouziel Slama (ouziel-slama)

documentation

https://docs.rs/zeldhash-parser

README

zeldhash-parser

Tests Coverage Format Clippy Crates.io

A high-performance Bitcoin blockchain parser implementing the ZeldHash protocol.

Built on zeldhash_protocol, this parser leverages protoblock for blazing-fast block fetching and rollblock for efficient UTXO management with instant rollback support.

Features

  • πŸš€ Maximum Performance β€” Parallel block fetching via protoblock with configurable thread pools
  • ⚑ Instant Rollbacks β€” rollblock provides chain reorganization handling
  • 🌐 Multi-Network β€” Supports Mainnet, Testnet4, Signet, and Regtest
  • πŸ“Š Live Progress β€” Terminal UI powered by ratatui
  • πŸ”§ Daemon Mode β€” Run as a background service with signal handling

Installation

cargo install zeldhash-parser

Or build from source:

git clone https://github.com/ouziel-slama/zeldhash-parser
cd zeldhash-parser
cargo build --release

Quick Start

# Parse mainnet (connects to local Bitcoin Core RPC)
zeldhash-parser

# Parse testnet4
zeldhash-parser --network testnet4

# Run as daemon
zeldhash-parser --daemon

# Stop daemon
zeldhash-parser stop

Configuration

Configuration can be provided via CLI flags, environment variables, or a TOML file.

Default config location: ~/.config/zeldhash/zeldhash-parser/zeldhash-parser.toml

Example configuration with production-optimized values (defaults are more conservative):

# Network: mainnet, testnet4, signet, regtest
network = "mainnet"

# Data directory for SQLite stats and rollblock storage
data_dir = "/path/to/data"

[protoblock]
rpc_url = "http://127.0.0.1:8332"
rpc_user = "bitcoin"
rpc_password = "password"
thread_count = 8              # default: 4
max_batch_size_mb = 256       # default: 10

[rollblock]
user = "zeld"                 # change this in production
password = "zeld"             # change this in production
port = 9443
shards_count = 16
thread_count = 4
initial_capacity = 100_000_000  # default: 5_000_000

The embedded rollblock server binds to 127.0.0.1 with basic authentication. By default it uses the zeld/zeld credentials on port 9443; change these via --rollblock_user, --rollblock_password, and --rollblock_port. The parser emits a startup warning when the defaults are still in use.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       zeldhash-parser                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  protoblock β”‚  β”‚ zeldhash_protocolβ”‚  β”‚     rollblock       β”‚  β”‚
β”‚  β”‚  ───────────│  β”‚  ───────────│  β”‚  ─────────────────  β”‚  β”‚
β”‚  β”‚  Fast block β”‚  β”‚  ZELD       β”‚  β”‚  UTXO store with    β”‚  β”‚
β”‚  β”‚  fetching & β”‚  β”‚  protocol   β”‚  β”‚  instant rollback   β”‚  β”‚
β”‚  β”‚  processing β”‚  β”‚  logic      β”‚  β”‚  support            β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                           β”‚                                  β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚                    β”‚   SQLite    β”‚                          β”‚
β”‚                    β”‚   (stats)   β”‚                          β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CLI Reference

Usage: zeldhash-parser [OPTIONS] [COMMAND]

Commands:
  run   Start the parser (default)
  stop  Stop the running daemon

Options:
  -c, --config <FILE>       Path to config file
  -d, --data-dir <DIR>      Data directory
  -n, --network <NETWORK>   Bitcoin network [mainnet|testnet4|signet|regtest]
      --daemon              Run as background daemon
  -h, --help                Print help
  -V, --version             Print version

Requirements

  • Rust 1.75+ (2021 edition)
  • Bitcoin Core node with RPC enabled
  • ~50GB+ disk space for mainnet UTXO set

Data Storage

SQLite Stats Database

The parser stores protocol statistics in zeldstats.sqlite3 with two tables:

-- Individual rewards per block
CREATE TABLE rewards (
    block_index INTEGER NOT NULL,
    txid TEXT NOT NULL,
    vout INTEGER NOT NULL,
    zero_count INTEGER NOT NULL,
    reward INTEGER NOT NULL,
    address TEXT,                -- Bitcoin address (NULL for non-standard scripts)
    PRIMARY KEY (block_index, txid, vout)
);

-- Per-block and cumulative stats (JSON-encoded)
CREATE TABLE stats (
    block_index INTEGER PRIMARY KEY,
    block_stats TEXT NOT NULL,   -- {"block_index":..., "total_reward":..., "reward_count":..., ...}
    cumul_stats TEXT NOT NULL    -- cumulative totals up to this block
);

Example: Query rewards with sqlite3

sqlite3 /path/to/data/zeldstats.sqlite3 \
  "SELECT txid, zero_count, reward, address FROM rewards WHERE block_index = 870000;"

Rollblock UTXO Store

UTXOs are stored in a rollblock key-value store for O(1) lookups and instant rollbacks.

Key format: Each UTXO is identified by a 12-byte key computed with the helper exposed by zeldhash-protocol:

use bitcoin::Txid;
use xxhash_rust::xxh3::xxh3_128;

fn compute_utxo_key(txid: &Txid, vout: u32) -> [u8; 12] {
    let mut payload = [0u8; 36];
    payload[..32].copy_from_slice(txid.as_ref());       // 32-byte txid
    payload[32..].copy_from_slice(&vout.to_le_bytes()); // 4-byte vout (LE)
    let hash = xxh3_128(&payload).to_le_bytes();        // xxHash128 β†’ take first 12 bytes
    let mut key = [0u8; 12];
    key.copy_from_slice(&hash[..12]);                   // truncate to 96 bits
    key
}

Value format: The ZELD UTXO balance stored as a little-endian u64.

Example: Read UTXO balances with rollblock client

use rollblock::client::{ClientConfig, RemoteStoreClient};
use rollblock::net::BasicAuthConfig;
use zeldhash_protocol::protocol::compute_utxo_key;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to rollblock server
    let auth = BasicAuthConfig::new("your_user", "your_password");
    let config = ClientConfig::without_tls(auth);
    let mut client = RemoteStoreClient::connect("127.0.0.1:9443", config)?;

    // Compute UTXO key for txid:vout
    let txid_hex = "abc123..."; // your txid
    let vout: u32 = 0;
    let txid = bitcoin::Txid::from_hex(txid_hex)?;
    let key = compute_utxo_key(&txid, vout);

    // Fetch balance
    let value = client.get_one(key)?;
    let balance = u64::from_le_bytes(value.try_into().unwrap_or([0; 8]));
    println!("Balance: {} sats", balance);

    client.close()?;
    Ok(())
}

License

Licensed under either of:

at your option.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Commit count: 17

cargo fmt