Strand
Merkle and Bitfield
Generate Merkle proofs and inspect a separate local-presence bitfield.
Strand::proof and verify_proof expose the stored tree’s verification path. Bitfield tracks local block presence; a bit is not proof that a remote peer has served verified data. Merkle nodes use flat-tree indexes: leaf indexes are even. The example below builds an independent fixture tree.
This example is checked against source signatures; it was not compiled or run during this documentation pass.
use strand::{Bitfield, MerkleTree, Node, Strand, StrandConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build a local strand and request a Merkle proof for an interior block.
let dir = tempfile::tempdir()?;
let mut strand = Strand::new(StrandConfig::new().with_storage(dir.path())).await?;
for payload in [b"alpha".as_slice(), b"beta", b"gamma", b"delta"] {
strand.append(payload).await?;
}
let target_seq: u64 = 2;
let proof = strand.proof(target_seq).await?;
let ok = strand.verify_proof(&proof, b"gamma").await?;
assert!(ok, "proof must verify for the original payload");
// Reconstruct a MerkleTree directly from leaf nodes to confirm the public surface.
let mut tree = MerkleTree::new();
for (i, leaf_hash) in [[1u8; 32], [2u8; 32], [3u8; 32], [4u8; 32]].into_iter().enumerate() {
tree.add(Node { index: (i as u64) * 2, size: 1, hash: leaf_hash });
}
let root = tree.root_hash();
// Model local presence: mark three slots and inspect the first unset slot.
let mut have = Bitfield::with_capacity(8);
have.set_range(0, 3, true);
let next_missing = have.first_unset();
println!(
"verified seq={} proof_nodes={} tree_root={} peer_have_count={} next_missing={:?}",
target_seq,
proof.nodes.len(),
hex::encode(root),
have.count(),
next_missing,
);
Ok(())
}