| Crates.io | shia |
| lib.rs | shia |
| version | 0.1.0 |
| created_at | 2025-11-04 00:04:28.983116+00 |
| updated_at | 2025-11-04 00:04:28.983116+00 |
| description | The BSV BEEF Protocol Reference Implementation |
| homepage | |
| repository | https://github.com/murphsicles/shia |
| max_upload_size | |
| id | 1915470 |
| size | 101,292 |
A Rust crate implementing the BSV BEEF (Background Evaluation Extended Format) protocol (BRC-62) for Simplified Payment Verification (SPV) on Bitcoin SV. It supports parsing, serialization, building from transaction DAGs, and verification of transactions with Merkle proofs using BUMP (BRC-74). Designed for integration into BSV wallet stacks, with script evaluation via the rust-sv crate. Includes support for atomic BEEF (BRC-95) and hooks for Paymail envelopes (BRC-70).
rust-sv).BlockHeadersClient trait for custom header oracles (e.g., local index, remote Pulse API). Optional Paymail envelope wrapping (feature-gated).thiserror (e.g., Parse("Extra bytes"), Verification("Missing UTXO"), AtomicMismatch).nour for BSV-specific tx/script handling (P2P, sighash, etc.).Add to your Cargo.toml:
[dependencies]
shia = "0.1.0"
For development (from GitHub, latest on dev branch):
[dependencies]
shia = { git = "https://github.com/murphsicles/shia", branch = "dev" }
For Paymail support (optional):
[dependencies]
shia = { version = "0.1.0", features = ["paymail"] }
use shia::Beef;
use hex_literal::hex;
let beef_hex = "efbe00010001"; // Minimal: version (0100BEEF LE) + nBumps=0 + nTxs=1 + tx raw + flag=00
let tx_raw = hex!("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0504ffff001dffffffff0100ca9a3b000000001976a914000000000000000000000000000000000000000088ac00000000");
let minimal_beef_hex = format!("efbe00010001{}{}", hex::encode(&tx_raw), "00");
let beef = Beef::from_hex(&minimal_beef_hex).expect("Valid BEEF");
let serialized = beef.serialize().expect("Serialize ok");
assert_eq!(hex::encode(serialized), minimal_beef_hex.to_lowercase());
use shia::{Beef, Transaction, Bump};
use std::collections::HashMap;
use hex_literal::hex;
let subject_raw = hex!("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0504ffff001dffffffff0100ca9a3b000000001976a914000000000000000000000000000000000000000088ac00000000");
let subject_tx = Transaction::from_raw(&subject_raw).unwrap();
// Example ancestor (parent tx)
let ancestor_raw = hex!("..."); // Parent tx raw bytes
let ancestor_tx = Transaction::from_raw(&ancestor_raw).unwrap();
let ancestors = HashMap::from([(ancestor_tx.txid(), ancestor_tx)]);
// Example bump for subject
let bump = Bump::new(subject_tx.merkle_hash(), vec![], 1); // Simplified
let bump_map = HashMap::from([(subject_tx.txid(), bump)]);
let beef = Beef::build(subject_tx, ancestors, bump_map, false).unwrap(); // Non-atomic
assert_eq!(beef.txs.len(), 2); // Subject + ancestor
use shia::client::BlockHeadersClient;
// Implement trait for your header source (e.g., local DB, remote API)
struct MyHeadersClient;
impl BlockHeadersClient for MyHeadersClient {
fn is_valid_root_for_height(&self, root: [u8; 32], height: u64) -> bool {
// Query your headers: e.g., check if root matches block at height
true // Mock: always valid
}
}
let mock_client = MyHeadersClient;
beef.verify(&mock_client).expect("SPV valid: roots, fees, scripts");
For single-subject graphs (e.g., micropayments), enable atomic mode:
let atomic_beef = Beef::build(subject_tx, ancestors, bump_map, true).unwrap();
assert!(atomic_beef.is_atomic);
atomic_beef.verify(&mock_client).expect("Atomic valid: no extraneous txs");
// Validation enforces: txs.len() == ancestors.len(), all trace to subject
BSV txids are the reversed bytes of double-SHA256(raw tx) for display/hex (big-endian convention). merkle_hash() returns unreversed for BUMP leaves.
Example (Genesis Coinbase):
let genesis_raw = hex!("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
let tx = Transaction::from_raw(&genesis_raw).unwrap();
let txid = tx.txid(); // [0x4a, 0x5e, ... 0x3b] → "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
let merkle = tx.merkle_hash(); // Unreversed for proofs
src/tx.rs: BSV Transaction wrapper—parsing (from_raw), hashing (txid/merkle_hash), script verification (verify_scripts with UTXO map).src/bump.rs: BRC-74 Bump struct—serialization, Merkle root computation for tx hashes.src/beef.rs: Core Beef struct—build (build), parse (from_hex/deserialize), verify (verify), serialize.src/atomic.rs: BRC-95 validation—validate_atomic ensures ancestry-only graphs.src/client.rs: BlockHeadersClient trait for Merkle root checks (e.g., against Teranode/Galaxy).src/utils.rs: VarInt read/write, double-SHA256 helpers.src/errors.rs: Comprehensive errors (Parse, Verification, ScriptEval, AtomicMismatch, etc.).Run with cargo test --lib for unit tests (parsing, building, verification, scripts). Doctests via cargo test --doc. CI (GitHub Actions) covers Rustfmt, Clippy, and full suite on push/PR. 100% coverage on core paths; includes genesis tx, P2PKH eval, topo-sort cycles.
Example failing case (pre-fix): Extra bytes in tx raw → Parse("Extra bytes after transaction").
byteorder, hex, thiserror, anyhow, sha2.sv (from GitHub: git+https://github.com/murphsicles/rust-sv.git).MIT License. See LICENSE for details.
git clone https://github.com/murphsicles/shia.git checkout -b feature/my-update.cargo test --lib --doc.cargo fmt && cargo clippy.dev branch with description/tests.Issues/PRs at GitHub. Focus on BSV scalability!
murphsicles – Built for the BSV Freedom Stack & Galaxy Node architecture. Questions? Open an issue!