A Bitcoin full node written in Python and Rust.
Maybe you've wondered what it takes to validate a Bitcoin transaction from scratch. ouroboros is a from-scratch Bitcoin full node that does exactly that. The heavy lifting (block sync, chain validation) is handled in Rust for performance, while Python handles the node logic, RPC server, and mempool.
- Block header sync and validation
- Full block download and storage
- Proof of work validation
- BIP66 (DERSIG) strict signature encoding
- BIP65/112 (CLTV/CSV) time locks
- BIP16 P2SH push-only scriptSig enforcement
- BIP141 SegWit support (P2WPKH, P2WSH)
- BIP146 NULLFAIL enforcement
- BIP141 WITNESS_PUBKEYTYPE (compressed keys in witness v0)
- BIP141 witness cleanstack (exactly one true element after execution)
- BIP141 MINIMALIF (OP_IF/OP_NOTIF must use minimal boolean encoding)
- Legacy sighash (FindAndDelete, OP_CODESEPARATOR, all sighash types)
- Script interpreter with stack operations and control flow (IF/ELSE/ENDIF)
- Mempool with ancestor/descendant limits (25 txs, 101KB)
- TRUC (v3 transaction) policy and ephemeral dust
- BIP125 Replace-By-Fee (RBF) with full RBF support (mempoolfullrbf)
- Pre-handshake peer filtering (reject old protocol versions, timeout)
- BIP339 WTXIDRELAY and BIP155 SENDADDRV2 negotiation
- BIP155 addrv2 message format (Tor v3, I2P, CJDNS addresses)
- Transaction trickling (privacy-preserving relay with Poisson delays)
- Eclipse attack mitigations (bucketed addrman, /16 diversity, anchors, feelers)
- Stale tip detection and peer eviction (ConsiderEviction, extra outbound connection)
- sendrawtransaction RPC with maxfeerate, confirmed/mempool checks, detailed errors
- getrawtransaction RPC with txindex support, verbose output, and in_active_chain
- Bitcoin Core-compatible RPCs (getblockchaininfo, getmempoolinfo, getpeerinfo, etc.)
- JSON-RPC batch request support (array of calls in single HTTP request)
- Package relay and CPFP (child-pays-for-parent) package acceptance
- submitpackage RPC for package submission (child-with-parents topology)
- BIP331 P2P messages (sendpackages, getpkgtxns, pkgtxns, ancpkginfo)
- PSBT (BIP174/BIP370) creation, signing, combining, and finalization
- Taproot PSBT fields (key path sigs, script path, internal key)
- Output descriptors (BIP380-386): pk, pkh, wpkh, tr, sh, wsh, multi, sortedmulti, combo, addr, raw
- Descriptor RPCs: getdescriptorinfo, deriveaddresses, importdescriptors, listdescriptors
- Miniscript (BIP379): parsing, type checking, compilation to Script, witness size analysis
- Miniscript fragments: pk, pkh, older, after, sha256, hash256, ripemd160, hash160
- Miniscript combinators: and_v, and_b, or_b, or_c, or_d, or_i, andor, thresh, multi, multi_a
- Miniscript wrappers: a:, s:, c:, d:, v:, j:, n:, t:, l:, u:
- Miniscript in descriptors: wsh(miniscript), tr(KEY, TREE)
- REST interface for block explorers (block, tx, headers, utxos, mempool, chaininfo)
- decoderawtransaction and decodescript RPCs
- getbalance and signrawtransactionwithwallet RPCs
- Signature verification cache (LRU, cleared on reorg)
- Full signature verification (secp256k1)
- Wallet functionality
# Install dependencies and build
./setup.sh
source .venv/bin/activate
# Sync testnet4 (faster for testing)
ouroboros --network testnet4 sync
# Check status
ouroboros statusouroboros/
├── ferrous-utils/sync/ # Rust: block sync, validation, PyO3 bindings
├── src/ouroboros/ # Python: CLI, RPC, mempool, node logic
│ ├── rpc.py # JSON-RPC server (FastAPI)
│ ├── rest.py # REST interface for block explorers
│ ├── mempool.py # Transaction mempool
│ ├── node.py # Node orchestration
│ ├── psbt.py # PSBT (BIP174/BIP370) support
│ ├── descriptors.py # Output descriptors (BIP380-386)
│ ├── miniscript.py # Miniscript (BIP379) support
│ ├── sig_cache.py # Signature verification cache
│ └── validation.py # Transaction/block validation
└── pyproject.toml
# Python tests
pytest
# Rust tests
cargo test --workspace
# Rebuild Rust extension after changes
maturin develop --manifest-path ferrous-utils/sync/Cargo.toml