A high-performance Bitcoin address collision searcher. Generates random private/public key pairs using secp256k1 elliptic curve cryptography and checks them against funded Bitcoin addresses.
- High Performance: ~4M addresses/sec on Apple M4 Max, ~700-800K on M1
- Fully Offline: No APIs or network traffic required once set up
- Multiple Address Types: P2PKH, P2WPKH, P2SH-P2WPKH (~87% of Bitcoin supply)
- Fast Balance Checking: Bloom filter + SQLite with hash160 optimization
- Native UIs: SwiftUI for macOS, egui for cross-platform
| egui (Cross-platform) | macOS (Native) |
|---|---|
![]() |
![]() |
- Rust 1.70+: Install via rustup (not needed for macOS release)
- Funded address database: Required before running (see below)
Note: The macOS release includes a bundled database of addresses with 1+ BTC. You can run it immediately - no setup required. The instructions below are for building from source or updating the database.
The app needs a database of funded Bitcoin addresses to check against.
Download addresses from Blockchair:
- Go to Blockchair Dumps
- Download the latest
blockchair_bitcoin_addresses_latest.tsv.gz - Extract it:
gunzip blockchair_bitcoin_addresses_latest.tsv.gz
The TSV file format is: address<tab>balance (one per line), e.g.:
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa 7204529884
3D2oetdNuZUqQHPJmcMDDHYoqkyNVsFk9r 5674283947
bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh 2134982374
Import addresses (filter to 1+ BTC for smaller database):
cargo run --release --bin import_addresses -- blockchair_bitcoin_addresses_latest.tsv --min-balance 100000000This creates data/bloom.bin (~3.5 MB) and data/funded_addresses.db (~115 MB for 1+ BTC addresses).
cargo run --release# Build the Rust library for macOS
./scripts/build-xcframework.sh
# Open and run in Xcode (Cmd+R to build & run)
open apple/macOS/BTCollider.xcodeprojNote: Set your Development Team in Xcode (Signing & Capabilities) before building.
macOS Settings: Database paths and performance settings are persisted and restored on app restart. Configure via Settings (⌘,).
btcollider/
├── crates/
│ ├── btcollider-core/ # Platform-agnostic Rust library
│ │ ├── src/
│ │ │ ├── address.rs # Bitcoin address encoding
│ │ │ ├── balance.rs # Bloom filter + SQLite
│ │ │ ├── config.rs # Configuration parsing
│ │ │ ├── engine.rs # Collision search engine
│ │ │ ├── ffi.rs # C FFI for Swift
│ │ │ └── metrics.rs # Performance metrics
│ │ └── include/ # C headers for FFI
│ │
│ └── btcollider-egui/ # Cross-platform GUI (Linux/Windows/macOS)
│ └── src/
│ ├── main.rs # egui app entry point
│ └── gui/ # UI panels
│
├── apple/ # Apple platform apps
│ ├── BTCollider/ # Swift package
│ │ └── Sources/
│ │ ├── BTColliderCore/ # Swift wrapper for Rust FFI
│ │ ├── BTColliderUI/ # Shared SwiftUI views
│ │ └── CBTColliderCore/ # C bridge module
│ │
│ └── macOS/ # macOS Xcode project
│
└── scripts/
└── build-xcframework.sh # Build Rust for Apple platforms
Copy and customize the example configuration:
cp config.toml.example config.toml[cpu]
batch_size = 65536 # Keys per batch
[workers]
count = 1 # Worker threads (rayon handles parallelism)
[addresses]
types = ["p2pkh", "p2wpkh", "p2sh-p2wpkh"]
[database]
bloom_path = "data/bloom.bin"
db_path = "data/funded_addresses.db"Results are auto-saved immediately when a match is found. On first run, a sample entry is created so you can verify the output file location. Previously saved results are loaded and displayed when the app starts.
| Platform | Path | Format |
|---|---|---|
| egui | results.json (configurable) |
JSON-lines (one object per line) |
| macOS | ~/Documents/btcollider_results.json |
JSON array |
Each result includes the private key in both WIF (wallet-importable) and hex formats:
egui (JSON-lines):
{"address":"1ABC...","private_key_wif":"KwDiBf89...","private_key_hex":"e8f32e...","balance_satoshi":5000000000,"found_at":"2025-12-28T10:30:00Z"}macOS (JSON array):
[{"address":"1ABC...","privateKeyWif":"KwDiBf89...","privateKeyHex":"e8f32e...","balanceSatoshi":5000000000,"foundAt":"2025-12-28T10:30:00Z"}]On first run, a sample entry is written with _SAMPLE suffix and 1 satoshi balance:
{"address":"1SampleAddressXXXXXXXXXXXXXXX_SAMPLE","private_key_wif":"KwDiBf89...SAMPLE","private_key_hex":"0000...SAMPLE","balance_satoshi":1,"found_at":"2000-01-01T00:00:00Z"}This lets you verify:
- Where results will be saved
- That new results are being appended (egui) or the array is growing (macOS)
The private_key_wif field is in Wallet Import Format - it can be directly imported into any Bitcoin wallet. WIF keys for compressed mainnet addresses start with K or L.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Key Generation │────▶│ Bloom Filter │────▶│ SQLite Verify │
│ (secp256k1) │ │ (hash160 bytes) │ │ (confirmation) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ 65K keys/batch │ ~0.1% pass │
▼ ▼ ▼
Thread-local Address Encoding Match found!
Secp256k1 ctx (only for positives)
The bloom filter checks hash160 bytes directly, not encoded addresses:
Per public key:
1. key_hash = hash160(pubkey) → covers P2PKH + P2WPKH
2. script_hash = hash160(redeemScript) → covers P2SH-P2WPKH
3. Only if bloom positive:
- Encode address (Base58/Bech32)
- Query SQLite
Result: 99.9% of keys skip expensive string encoding
| Type | Prefix | Coverage | Description |
|---|---|---|---|
| P2PKH | 1... |
43% | Legacy (Base58Check) |
| P2WPKH | bc1q... |
20% | Native SegWit (Bech32) |
| P2SH-P2WPKH | 3... |
24% | Wrapped SegWit (Base58Check) |
Total: ~87% of Bitcoin supply
Tested on Apple M4 Max: ~4M addresses/sec
The secp256k1 crate with NEON instructions + rayon parallelization provides optimal performance on Apple Silicon.
// Create engine
let engine = try CollisionEngine()
// Configure (before starting)
try engine.setBloomPath("path/to/bloom.bin")
try engine.setDatabasePath("path/to/db.sqlite")
try engine.setBatchSize(65536)
// Control
try engine.start()
try engine.pause()
try engine.resume()
engine.stop()
// Observe (via @Published properties)
engine.state // .idle, .running, .paused
engine.metrics // Metrics struct
engine.foundAddresses // [FoundAddress]use btcollider_core::{CollisionEngine, Config};
let config = Config::load();
let mut engine = CollisionEngine::new(config);
engine.set_match_callback(|result| {
println!("Found: {} with {} sats", result.address, result.balance);
});
engine.start()?;
// ... engine runs in background
engine.stop()?;# Run all tests
cargo test --release
# Core library only
cargo test --release -p btcollider-coreThis project is for educational and research purposes. The probability of finding a collision is astronomically small (~1 in 2^160). Claiming funds from addresses you don't own may be illegal in your jurisdiction.
- Large Bitcoin Collider - Original concept
- rust-secp256k1 - Optimized elliptic curve library
- egui - Immediate mode GUI framework

