bitcoin-heuristics 0.1.0

Pattern detection heuristics for Bitcoin on-chain analytics — consolidations, distributions, CoinJoin, fee spikes, dormant supply reactivation and more
Documentation

bitcoin-heuristics

Crates.io Docs.rs CI License: MIT

Pattern detection heuristics for Bitcoin on-chain analytics.

Detects consolidations, distributions, CoinJoin, fee spikes, dormant supply reactivation, and more — from pre-extracted TxFeatures. No blockchain node required for most heuristics.

Features

  • 8 bundled heuristics — consolidation, distribution, CoinJoin detection, urgent execution (fee spike), address reuse, round value, HFT consolidation, long-term supply activation
  • 6 analyzer modules — topology, UTXO age classification, change detection, fee percentile, Lightning detection, BTC price encoding
  • 20 classification enums — FeeRateTier, StructuralPattern, ScriptType, CoinJoinScore, LightningIndicator, and more
  • Zero async runtime — synchronous design, ureq for optional RPC calls
  • No database dependencies — pure computation on TxFeatures, works standalone
  • Extensible — implement the Heuristic trait to add custom detectors

Quick Start

[dependencies]
bitcoin-heuristics = "0.1"
use bitcoin_heuristics::{HeuristicRegistry, TxFeatures};

let features = TxFeatures {
    input_count: 15,
    output_count: 2,
    is_consolidation: true,
    total_input_value: 200_000_000, // 2 BTC in satoshis
    is_input_script_homogeneous: true,
    output_value_max: 180_000_000,
    total_output_value: 199_995_000,
    block_price_usd: Some(60_000.0),
    ..TxFeatures::default()
};

let registry = HeuristicRegistry::default_registry(0.7); // coinjoin threshold
let matches = registry.evaluate_all(&features);

for m in &matches {
    println!("[{}] {}{}", m.event_type, m.pattern, m.summary);
}

Custom Heuristic

use bitcoin_heuristics::{Heuristic, HeuristicMatch, HeuristicStatus, TxFeatures};
use evidence_chain::EvidenceChain;
use serde_json::json;

struct MyHeuristic;

impl Heuristic for MyHeuristic {
    fn id(&self) -> &'static str { "my-heuristic-v1" }
    fn version(&self) -> &'static str { "1.0.0" }
    fn status(&self) -> HeuristicStatus { HeuristicStatus::Experimental }

    fn evaluate(&self, f: &TxFeatures) -> Option<HeuristicMatch> {
        if f.output_count > 100 {
            Some(HeuristicMatch::new(
                self.id(), self.version(),
                "high_fan_out", "structural", self.trigger_scope(),
                format!("{} outputs detected", f.output_count),
                serde_json::json!({ "output_count": f.output_count }),
            ))
        } else {
            None
        }
    }

    fn build_evidence(&self, _: &TxFeatures) -> Option<EvidenceChain> { None }
}

Long-Term Supply Activation (RPC)

The LongTermSupplyActivationHeuristic requires Bitcoin RPC access to fetch UTXO ages:

use bitcoin_heuristics::{JsonRpcClient, LongTermSupplyActivationHeuristic};

let rpc = JsonRpcClient::new("http://127.0.0.1:8332", "user", "pass");
// Second param: minimum UTXO age in blocks (~3 years = 157_680 blocks)
let h = LongTermSupplyActivationHeuristic::new(rpc, 157_680);

Heuristics Reference

ID Trigger Description
institutional-consolidation-v1 tx ≥10 inputs → ≤3 outputs, >$100k USD, homogeneous scripts
institutional-distribution-v1 tx ≤3 inputs → ≥20 outputs, >$50k USD, homogeneous outputs
coinjoin-detection-v1 tx CoinJoin score ≥ threshold, ≥5 inputs/outputs, equal outputs
urgent-execution-v1 tx Fee rate spike above configured threshold
address-reuse-detection-v1 tx ≥60% address reuse ratio, ≥2 reused, ≥3 outputs
round-value-v1 tx Round output values, possible OTC / P2P trade signal
hft-consolidation-v1 block ≥100 fresh inputs (≤7 days), ≤3 outputs
long-term-supply-activation-v1 tx Dormant UTXOs (≥3 years) spent, >$50k USD (requires RPC)

License

MIT — see LICENSE.