
Building Bitcoin Applications with the Rust Bitcoin Library
Learn to build Bitcoin apps in Rust using rust-bitcoin for transaction parsing, key generation, and wallet creation with practical code examples.
The rust-bitcoin library has quietly become foundational infrastructure for serious Bitcoin development. With over 2,400 GitHub stars and 231 contributors, it powers everything from hardware wallet firmware to block explorers. If you're building Bitcoin tooling and want the safety guarantees that Rust provides, this is where you start.
This guide walks through integrating Rust Bitcoin into your project, from basic transaction parsing to constructing a functional wallet. We'll cover practical code patterns while being honest about where rust-bitcoin fits and where you'll need additional libraries.
What Rust Bitcoin Actually Does
The library handles Bitcoin protocol primitives: serialization and deserialization of transactions, blocks, scripts, addresses, and network messages. It supports BIP-32 hierarchical deterministic keys, Partially Signed Bitcoin Transactions (PSBT v0), and all the low-level data structures you need to work with Bitcoin programmatically.
What it doesn't do is equally important. Rust Bitcoin is not designed for consensus validation, as its implementation intentionally deviates from Bitcoin Core in some areas. Don't use it to validate blocks for a full node. It also doesn't handle networking, chain state, or wallet database management out of the box.
Think of it as the parsing and construction layer. You build higher-level functionality on top.
Setting Up Your Project
Add rust-bitcoin to your `Cargo.toml`. The ecosystem has stabilized around version 0.32, which received long-term support designation in 2025:
```toml
[dependencies]
bitcoin = "0.32"
```
The minimum supported Rust version is 1.74.0. If you're maintaining legacy systems, check your toolchain.
For a complete application, you'll likely need companion crates. The secp256k1 crate handles elliptic curve operations, while base58ck manages Base58Check encoding. Both were updated as part of the 0.32 release wave with OpenSats funding support in August 2025.
Parsing Transactions
Let's start with the Bitcoin equivalent of "Hello World": decoding a raw transaction. This is the same operation as Bitcoin Core's `decoderawtransaction` RPC.
```rust
use bitcoin::consensus::deserialize;
use bitcoin::Transaction;
fn parse_transaction(hex_string: &str) -> Result<Transaction, Box<dyn std::error::Error>> {
let raw_tx = hex::decode(hex_string)?;
let tx: Transaction = deserialize(&raw_tx)?;
Ok(tx)
}
```
Once parsed, you can inspect inputs, outputs, witness data, and compute the transaction ID:
```rust
let txid = tx.compute_txid();
println!("Transaction ID: {}", txid);
println!("Input count: {}", tx.input.len());
println!("Output count: {}", tx.output.len());
for (i, output) in tx.output.iter().enumerate() {
println!("Output {}: {} sats", i, output.value.to_sat());
}
```
This pattern, decode from bytes, work with structured data, encode back to bytes, appears throughout rust-bitcoin development.
Generating Keys and Addresses
Creating a Bitcoin address requires generating a private key, deriving the public key, and encoding it appropriately for the network:
```rust
use bitcoin::secp256k1::{rand, Secp256k1};
use bitcoin::{Address, Network, PrivateKey, PublicKey};
fn generate_address() -> (PrivateKey, Address) {
let secp = Secp256k1::new();
let (secret_key, public_key) = secp.generate_keypair(&mut rand::thread_rng());
let private_key = PrivateKey::new(secret_key, Network::Bitcoin);
let public_key = PublicKey::new(public_key);
// Generate a native SegWit (bech32) address
let address = Address::p2wpkh(&public_key, Network::Bitcoin)
.expect("valid public key");
(private_key, address)
}
```
For production wallets, you wouldn't generate keys this way. You'd use BIP-39 mnemonics and BIP-32 derivation paths. Rust-bitcoin supports the derivation; for mnemonic handling, look at the bip39 crate.
Working with Scripts
Bitcoin's scripting system determines how funds can be spent. Rust-bitcoin provides builders for common script patterns:
```rust
use bitcoin::script::Builder;
use bitcoin::opcodes::all::*;
use bitcoin::ScriptBuf;
// Create a P2PKH script
fn create_p2pkh_script(pubkey_hash: &[u8; 20]) -> ScriptBuf {
Builder::new()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
.push_slice(pubkey_hash)
.push_opcode(OP_EQUALVERIFY)
.push_opcode(OP_CHECKSIG)
.into_script()
}
```
For most applications, you won't construct scripts manually. The address types handle script creation internally. But understanding scripts becomes essential when building multisig setups or custom spending conditions.
Building Transactions
Constructing a transaction from scratch requires specifying inputs (which UTXOs you're spending), outputs (where the funds go), and later adding signatures:
```rust
use bitcoin::{Transaction, TxIn, TxOut, Sequence, Witness};
use bitcoin::absolute::LockTime;
use bitcoin::transaction::Version;
use bitcoin::Amount;
fn create_unsigned_transaction(
input_txid: bitcoin::Txid,
input_vout: u32,
recipient: Address,
amount: Amount,
) -> Transaction {
let input = TxIn {
previous_output: bitcoin::OutPoint::new(input_txid, input_vout),
script_sig: ScriptBuf::new(), // Empty for SegWit
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
witness: Witness::default(),
};
let output = TxOut {
value: amount,
script_pubkey: recipient.script_pubkey(),
};
Transaction {
version: Version::TWO,
lock_time: LockTime::ZERO,
input: vec![input],
output: vec![output],
}
}
```
This creates an unsigned transaction. Signing requires knowing the previous output's script and value, computing the sighash, and producing a valid signature. For anything beyond toy examples, use PSBT.
PSBT for Real Wallet Workflows
Partially Signed Bitcoin Transactions solve the coordination problem of signing. They're essential for hardware wallets, multisig setups, and any workflow where different parties contribute to a transaction:
```rust
use bitcoin::psbt::Psbt;
fn create_psbt(unsigned_tx: Transaction) -> Psbt {
Psbt::from_unsigned_tx(unsigned_tx)
.expect("valid unsigned transaction")
}
```
PSBT objects carry metadata about inputs (previous transactions, derivation paths, partial signatures) that signers need. You can serialize them, pass them between devices or services, and combine partial signatures until the transaction is fully signed.
When to Use BDK Instead
For wallet applications, consider the Bitcoin Development Kit (BDK), which builds on rust-bitcoin. BDK handles UTXO tracking, coin selection, fee estimation, and database persistence, all the wallet logic that rust-bitcoin intentionally excludes.
Rust-bitcoin is the right choice when you need low-level control: building a block explorer, implementing custom signing logic, parsing blockchain data, or creating Bitcoin-adjacent tools. BDK is better when you want a functional wallet without reimplementing standard patterns.
The July 2025 tutorial on building a Bitcoin CLI wallet demonstrates this split well: rust-bitcoin for protocol understanding, BDK for the heavy lifting.
Security Considerations
Rust's memory safety eliminates entire classes of vulnerabilities common in C/C++ Bitcoin implementations. But library choice doesn't automatically make your application secure.
Verify your dependencies. The rust-bitcoin maintainers recommend cargo-crev for dependency auditing. The library includes fuzzing and mutation testing in its CI pipeline, but your application code needs similar scrutiny.
Key management remains the hard problem. Rust-bitcoin gives you the cryptographic primitives; protecting private keys in memory, securing storage, and handling hardware wallet communication are your responsibility.
Connecting to the Network
Rust-bitcoin doesn't include networking. To broadcast transactions or fetch blockchain data, you'll need additional infrastructure:
rust-bitcoincore-rpc connects to a local Bitcoin Core node via JSON-RPC. This is the most reliable option if you're running your own node.
Electrum protocol libraries let you query public servers without running a full node, with the usual privacy and trust tradeoffs.
Esplora clients provide REST API access to block explorers.
Choose based on your trust model. A self-hosted Bitcoin Core node gives you verification; third-party services give you convenience.
Moving Forward
The rust-bitcoin ecosystem has matured significantly. The 0.32 LTS release provides stability for production applications, and the modular crate structure lets you include only what you need.
For deeper study, Lukáš Hozda's "Building Bitcoin in Rust" covers implementing a full library, miner, and wallet from scratch. The official documentation at docs.rs/bitcoin remains the authoritative API reference.
Start small. Parse a transaction, generate an address, decode a block header. The primitives compose into complex applications, but each piece is understandable on its own terms. That's the real value of working at this level: you understand exactly what your code is doing with other people's money.