Skip to main content

Crate niebla_158

Crate niebla_158 

Source
Expand description

niebla-158: a compact-filter (BIP-158) client engine for wallets.

§What you implement

  • FilterSource: fetch cfheaders batches, per-block filters, and raw blocks.
  • WalletHooks: provide a watchlist and handle on_block_match callbacks.
  • Store: keep a couple of integers (verified tip + last scanned).
  • [HeaderSource]: return block header info by height (used to scan ranges).

§What the engine does

  • Validates cfheaders against optional checkpoints (defense-in-depth).
  • Iterates new heights, pulls filters, tests against your watchlist.
  • On a hit, fetches the block, decodes transactions, and notifies you.

§Minimal usage

use niebla_158::prelude::*;
use bitcoin::{BlockHash, ScriptBuf, hashes::{sha256d, Hash as _}};
use async_trait::async_trait;

// --- Your implementations ---
struct MySource;
#[async_trait]
impl FilterSource for MySource {
    async fn get_cfheaders(&self, _start: u32, _stop: BlockHash) -> anyhow::Result<CfHeadersBatch> {
        Ok(CfHeadersBatch { start_height: 0, headers: vec![] })
    }
    async fn get_cfilter(&self, _block: BlockHash) -> anyhow::Result<Vec<u8>> { Ok(vec![]) }
    async fn get_block(&self, _block: BlockHash) -> anyhow::Result<Vec<u8>> { Ok(vec![]) }
}

struct MyHeaders;
#[async_trait]
impl HeaderSource for MyHeaders {
    async fn tip_height(&self) -> anyhow::Result<u32> { Ok(0) }
    async fn hash_at_height(&self, _h: u32) -> anyhow::Result<BlockHash> {
        Ok(BlockHash::from_raw_hash(sha256d::Hash::all_zeros()))
    }
}

struct MyStore;
#[async_trait]
impl Store for MyStore {
    async fn load_cf_tip(&self) -> anyhow::Result<Option<(u32, BlockHash)>> { Ok(None) }
    async fn save_cf_tip(&self, _h: u32, _cf: BlockHash) -> anyhow::Result<()> { Ok(()) }
    async fn get_last_scanned(&self) -> anyhow::Result<u32> { Ok(0) }
    async fn set_last_scanned(&self, _h: u32) -> anyhow::Result<()> { Ok(()) }
    async fn get_birth_height(&self) -> anyhow::Result<Option<u32>> { Ok(None) }
    async fn set_birth_height(&self, _h: u32) -> anyhow::Result<()> { Ok(()) }
}

struct MyWallet;
#[async_trait]
impl WalletHooks for MyWallet {
    async fn watchlist(&self) -> anyhow::Result<Vec<ScriptBuf>> { Ok(vec![]) }
    async fn on_block_match(
        &self, _h: u32, _b: BlockHash, _txs: Vec<bitcoin::Transaction>
    ) -> anyhow::Result<()> { Ok(()) }
}

// --- Wire it up ---
async fn run() -> anyhow::Result<()> {
    let engine = Niebla158::new(MyStore, MyWallet, MySource, MyHeaders);
    // Drive with an iterator of (height, header_hash); here empty:
    engine.run_to_tip(std::iter::empty()).await?;
    Ok(())
}

Re-exports§

pub use engine::Niebla158;
pub use filter_source::FilterSource;
pub use hooks::WalletHooks;
pub use store::sqlite_store::SqliteStore;
pub use store::Store;

Modules§

engine
Engine that verifies cfheaders, scans filters, and fetches matching blocks. Orchestrator for BIP-158 light client flow:
filter_source
Traits and types for fetching cfheaders, cfilters, and blocks from the network. Abstractions for fetching compact filter data from the network (HTTP or P2P).
headers
Block header lookup abstraction (height → hash).
hooks
Wallet callbacks: provide a watchlist and receive matches. Wallet glue: provide watchlist items and receive notifications on matches.
prelude
Convenience prelude for end users.
store
Persistence layer (traits and SQLite implementation). Persistence interfaces and implementations used by the engine (e.g., cfheaders tip and last scanned height).