https://github.com/defenwycke/bitcoin-reaper
Reaper: dead code detection engine for Bitcoin witness scripts. Static analysis of transaction witnesses to identify inscription envelopes, unreachable code, fake pubkeys, and excess data.
https://github.com/defenwycke/bitcoin-reaper
analysis bitcoin dead-code inscriptions script static-analysis witness
Last synced: 3 months ago
JSON representation
Reaper: dead code detection engine for Bitcoin witness scripts. Static analysis of transaction witnesses to identify inscription envelopes, unreachable code, fake pubkeys, and excess data.
- Host: GitHub
- URL: https://github.com/defenwycke/bitcoin-reaper
- Owner: defenwycke
- License: mit
- Created: 2026-04-12T16:00:12.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-12T17:21:29.000Z (4 months ago)
- Last Synced: 2026-04-12T18:06:38.992Z (4 months ago)
- Topics: analysis, bitcoin, dead-code, inscriptions, script, static-analysis, witness
- Language: Rust
- Size: 66.4 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# bitcoin-reaper
**Reaper** is a dead code detection engine for Bitcoin witness scripts. It statically analyses transaction witnesses to identify bytes that serve no legitimate cryptographic purpose — inscription envelopes, unreachable code, fake pubkeys, data stuffing, and excess witness data.
## What it does
Reaper takes a `bitcoin::Transaction` and returns a detailed `ReaperVerdict`:
```rust
use bitcoin_reaper::{analyze, ReaperConfig};
let config = ReaperConfig::default(); // all detectors enabled
let verdict = analyze(&transaction, &config);
if verdict.is_corpse() {
println!("Dead code found: {} bytes in {} regions",
verdict.total_dead_bytes, verdict.dead_regions.len());
for region in &verdict.dead_regions {
println!(" {:?} at {:?}: {} bytes — {}",
region.dead_code_type, region.location,
region.size, region.description);
}
} else {
println!("Clean transaction — {} essential bytes",
verdict.total_essential_bytes);
}
```
## Detection capabilities
| Type | What it catches |
|------|----------------|
| **Inscription envelopes** | Ordinals `OP_FALSE OP_IF ... OP_ENDIF` patterns in witness |
| **Drop stuffing** | Data pushed then immediately `OP_DROP`'d (arbitrary data injection) |
| **Unreachable code** | Script paths after unconditional jumps (flow analysis) |
| **Fake pubkeys** | Data disguised as public keys but not valid curve points |
| **Excess witness data** | Witness bytes beyond what the script execution requires |
| **Excess stack items** | More stack items than the script consumes |
| **Annex data** | BIP-341 annex field (reserved, no current consensus meaning) |
| **Oversized OP_RETURN** | OP_RETURN outputs exceeding policy threshold |
| **Legacy scriptSig data** | Embedded data in legacy (non-segwit) inputs |
## Architecture
```
Transaction
│
├─ witness.rs identify spend type (P2TR script/key, P2WSH, legacy)
│
├─ dead_code.rs pattern detection (inscriptions, drop stuffing, fake pubkeys)
│
├─ flow.rs script flow analysis (trace execution paths)
│ └─ simulator.rs opcode-level script simulator
│
├─ essential.rs compute witness breakdown (essential vs dead bytes)
│
├─ legacy.rs legacy scriptSig analysis
│
├─ output.rs output analysis (OP_RETURN)
│
└─ verdict.rs ReaperVerdict with byte-level dead code regions
```
The key insight: Reaper doesn't just pattern-match known bad things. The **flow analyser** (`flow.rs` + `simulator.rs`) traces actual script execution paths to find code that is provably unreachable — regardless of what it contains. This catches novel dead code injection techniques that pattern matching would miss.
## Configuration
Individual detectors can be toggled:
```rust
let mut config = ReaperConfig::default();
config.detect_inscriptions = false; // ignore inscription envelopes
config.detect_drops = false; // ignore OP_DROP stuffing
// flow analysis always runs — it's the principled detector
```
## Verdict types
- **`Verdict::Accept`** — transaction has no significant dead code
- **`Verdict::Corpse`** — transaction contains dead code regions that exceed thresholds
Each verdict includes:
- `dead_regions`: byte-level map of every dead code region found
- `input_analyses`: per-input breakdown with spend type, script size, dead bytes
- `witness_breakdown`: essential vs dead bytes, essential vs actual stack items
- `dead_code_ratio`: fraction of witness that is dead code
- `total_dead_bytes` / `total_essential_bytes` / `total_excess_bytes`
## Tests
```bash
cargo test
# 119 tests — including 26 adversarial edge cases
```
## Use cases
- **Node operators**: filter transactions with excessive dead code from your mempool
- **Mining pools**: build cleaner block templates
- **Block explorers**: show dead code analysis alongside transaction details
- **Protocol researchers**: measure dead code prevalence across the blockchain
- **Security auditors**: identify novel data injection techniques
## Combining with other tools
Reaper analyses individual transactions. Pair it with:
- [bitcoin-buds](https://github.com/defenwycke/bitcoin-buds) — tier-based transaction classification and policy filtering
- [bitcoin-shroud](https://github.com/defenwycke/bitcoin-shroud) — transaction relay timing privacy
## Origin
Extracted from [Bitcoin Ghost](https://bitcoinghost.org) where Reaper has been running in production on Bitcoin mainnet nodes since March 2026, analysing live transaction traffic. The detection engine processes every transaction entering the mempool and provides the analytical foundation for Ghost's configurable content policy system.
## Licence
MIT