A Bitcoin-style full node and proof-of-work mining simulator written in Rust.
Rust
1
1 commits
updated Jul 17, 2026
A Bitcoin-style full node and proof-of-work mining simulator, written in Rust.
mini-bitcoin is a from-scratch cryptocurrency node that implements the core
machinery behind Bitcoin — proof-of-work mining, a longest-chain consensus rule,
cryptographically signed transactions, an account-based ledger, and a gossip P2P
network — small enough to read end to end, yet complete enough to spin up a
multi-node network that mines and converges on a single chain in real time.
It also ships with a built-in HTTP API and a live browser blockchain visualizer, so you can watch blocks, forks, and balances evolve as the network runs.
ring; 32-byte hashes (H256)
and 20-byte addresses (H160) derived from public keys.(nonce, balance) per address, updated as
blocks are applied; transactions are checked for valid signatures, sufficient
balance, and correct nonce (double-spend / replay protection).mio
TCP server speaking a compact message protocol:
Ping/Pong, NewBlockHashes, GetBlocks, Blocks, NewTransactionHashes,
GetTransactions, Transactions. New blocks and transactions propagate by
announce → request → relay. ┌─────────────────────────────────────────┐
│ Arc<Mutex<Blockchain>> │
│ longest-chain rule · orphan buffer · │
│ per-block ledger state │
└───────▲───────────────▲──────────────▲───┘
│ │ │
mines blocks │ applies│/serves │ reads
│ blocks &│txns │
┌─────────────┴──┐ ┌─────────┴──────┐ ┌───┴────────┐
│ Miner │ │ Network Worker│ │ API Server│
│ (PoW nonce │ │ (mio gossip, │ │ (tiny_http,│
│ search loop) │ │ P2P relay) │ │ visualizer)│
└───────┬────────┘ └───────┬────────┘ └────────────┘
│ │
│ ┌────────────────┴───────┐
└──▶│ Arc<Mutex<Mempool>> │◀── Transaction Generator
│ pending signed txns │ (background signer)
└─────────────────────────┘
Source layout (src/):
| Module | Responsibility |
|---|---|
crypto/ | hash (H256/SHA-256), key_pair (Ed25519), address (H160), merkle |
block.rs | block/header/content structs, genesis, hashing |
blockchain.rs | insertion, longest-chain fork-choice, orphan buffer, ledger state |
transaction.rs | transaction model, signing & verification |
transaction_generator.rs | background generator of signed transactions |
mempool.rs | pool of pending transactions |
miner.rs | proof-of-work mining loop and control handle |
network/ | server (mio), worker, peer, message protocol |
api/ | HTTP control + inspection endpoints, serves the visualizer |
resources/ | blockchain_visualizer.html |
Requires a stable Rust toolchain (rustup).
cargo build --release
Start a single node (P2P on 127.0.0.1:6000, API on 127.0.0.1:7000 by default):
cargo run --release
Command-line flags:
| Flag | Default | Description |
|---|---|---|
--p2p <ADDR> | 127.0.0.1:6000 | P2P server bind address |
--api <ADDR> | 127.0.0.1:7000 | HTTP API bind address |
-c, --connect <PEER> | — | Peer address(es) to dial on startup (repeatable) |
--p2p-workers <N> | 4 | Worker threads for the P2P server |
--difficulty <HEX> | 0x0fff…ff | Genesis PoW target, 64-char hex (32 bytes, big-endian). Smaller = harder. |
-v | — | Increase log verbosity (repeatable) |
Then start mining and watch the tip advance:
# lambda is the mining loop delay — larger = slower block production
curl "http://127.0.0.1:7000/miner/start?lambda=1000000"
curl http://127.0.0.1:7000/api/tip
Open http://127.0.0.1:7000/visualize in a browser to watch the chain grow.
Launch three nodes on one machine and wire them into a small network. Each mines independently; the gossip layer relays blocks and the longest-chain rule makes them converge on the same tip.
# Node 1 — seed
cargo run --release -- --p2p 127.0.0.1:6000 --api 127.0.0.1:7000
# Node 2 — connects to node 1
cargo run --release -- --p2p 127.0.0.1:6001 --api 127.0.0.1:7001 -c 127.0.0.1:6000
# Node 3 — connects to nodes 1 and 2
cargo run --release -- --p2p 127.0.0.1:6002 --api 127.0.0.1:7002 -c 127.0.0.1:6000 -c 127.0.0.1:6001
# Start mining on all three, then compare their tips — they should match.
for p in 7000 7001 7002; do curl -s "http://127.0.0.1:$p/miner/start?lambda=2000000"; done
for p in 7000 7001 7002; do echo "node $p:"; curl -s "http://127.0.0.1:$p/api/tip"; done
| Endpoint | Description |
|---|---|
GET /miner/start?lambda=<N> | Start mining; lambda sets the inter-block loop delay |
GET /network/ping | Broadcast a ping to connected peers |
GET /api/tip | Current tip hash and height |
GET /api/blocks?start=<h>&end=<h> | Blocks in a height range (hash, parent, height, timestamp, tx count) |
GET /blockchain/length | Total stored block count and tip height |
GET /blockchain/stats | Block/mined/received counts, avg block-propagation delay, avg block size |
GET /blockchain/state | Ledger state: per-address (nonce, balance) |
GET /visualize | Interactive HTML blockchain visualizer |
The /visualize endpoint serves a self-contained web page that polls /api/blocks
and /api/tip to render the chain as a growing graph — the main chain, any forks
and orphaned branches, and per-block metadata (height, timestamp, transaction
count). It updates live while the node mines, making forks and reorgs easy to see.
Because block production rate and network propagation are both configurable, the node doubles as a small testbed for blockchain dynamics:
--difficulty (and the lambda mining
delay) and read mined_count / tip_height from /blockchain/stats to observe
how the expected time-to-block scales with the size of the target space./api/tip. avg_delay_ms in /blockchain/stats reports
mean block-propagation delay; raising the mining rate relative to propagation
delay increases the fork rate, illustrating why real networks tune block time
well above network latency.Rust 2018 · ring (crypto) · mio / mio-extras / net2 (async networking) ·
crossbeam (channels) · serde / bincode / serde_json (serialization) ·
tiny_http (API) · clap (CLI) · ring-backed SHA-256 & Ed25519.
Released under the MIT License.
1 commits
Rust
81.1%
HTML
18.9%
A Bitcoin-style full node and proof-of-work mining simulator written in Rust.
Rust
1
1 commits
updated Jul 17, 2026
A Bitcoin-style full node and proof-of-work mining simulator, written in Rust.
mini-bitcoin is a from-scratch cryptocurrency node that implements the core
machinery behind Bitcoin — proof-of-work mining, a longest-chain consensus rule,
cryptographically signed transactions, an account-based ledger, and a gossip P2P
network — small enough to read end to end, yet complete enough to spin up a
multi-node network that mines and converges on a single chain in real time.
It also ships with a built-in HTTP API and a live browser blockchain visualizer, so you can watch blocks, forks, and balances evolve as the network runs.
ring; 32-byte hashes (H256)
and 20-byte addresses (H160) derived from public keys.(nonce, balance) per address, updated as
blocks are applied; transactions are checked for valid signatures, sufficient
balance, and correct nonce (double-spend / replay protection).mio
TCP server speaking a compact message protocol:
Ping/Pong, NewBlockHashes, GetBlocks, Blocks, NewTransactionHashes,
GetTransactions, Transactions. New blocks and transactions propagate by
announce → request → relay. ┌─────────────────────────────────────────┐
│ Arc<Mutex<Blockchain>> │
│ longest-chain rule · orphan buffer · │
│ per-block ledger state │
└───────▲───────────────▲──────────────▲───┘
│ │ │
mines blocks │ applies│/serves │ reads
│ blocks &│txns │
┌─────────────┴──┐ ┌─────────┴──────┐ ┌───┴────────┐
│ Miner │ │ Network Worker│ │ API Server│
│ (PoW nonce │ │ (mio gossip, │ │ (tiny_http,│
│ search loop) │ │ P2P relay) │ │ visualizer)│
└───────┬────────┘ └───────┬────────┘ └────────────┘
│ │
│ ┌────────────────┴───────┐
└──▶│ Arc<Mutex<Mempool>> │◀── Transaction Generator
│ pending signed txns │ (background signer)
└─────────────────────────┘
Source layout (src/):
| Module | Responsibility |
|---|---|
crypto/ | hash (H256/SHA-256), key_pair (Ed25519), address (H160), merkle |
block.rs | block/header/content structs, genesis, hashing |
blockchain.rs | insertion, longest-chain fork-choice, orphan buffer, ledger state |
transaction.rs | transaction model, signing & verification |
transaction_generator.rs | background generator of signed transactions |
mempool.rs | pool of pending transactions |
miner.rs | proof-of-work mining loop and control handle |
network/ | server (mio), worker, peer, message protocol |
api/ | HTTP control + inspection endpoints, serves the visualizer |
resources/ | blockchain_visualizer.html |
Requires a stable Rust toolchain (rustup).
cargo build --release
Start a single node (P2P on 127.0.0.1:6000, API on 127.0.0.1:7000 by default):
cargo run --release
Command-line flags:
| Flag | Default | Description |
|---|---|---|
--p2p <ADDR> | 127.0.0.1:6000 | P2P server bind address |
--api <ADDR> | 127.0.0.1:7000 | HTTP API bind address |
-c, --connect <PEER> | — | Peer address(es) to dial on startup (repeatable) |
--p2p-workers <N> | 4 | Worker threads for the P2P server |
--difficulty <HEX> | 0x0fff…ff | Genesis PoW target, 64-char hex (32 bytes, big-endian). Smaller = harder. |
-v | — | Increase log verbosity (repeatable) |
Then start mining and watch the tip advance:
# lambda is the mining loop delay — larger = slower block production
curl "http://127.0.0.1:7000/miner/start?lambda=1000000"
curl http://127.0.0.1:7000/api/tip
Open http://127.0.0.1:7000/visualize in a browser to watch the chain grow.
Launch three nodes on one machine and wire them into a small network. Each mines independently; the gossip layer relays blocks and the longest-chain rule makes them converge on the same tip.
# Node 1 — seed
cargo run --release -- --p2p 127.0.0.1:6000 --api 127.0.0.1:7000
# Node 2 — connects to node 1
cargo run --release -- --p2p 127.0.0.1:6001 --api 127.0.0.1:7001 -c 127.0.0.1:6000
# Node 3 — connects to nodes 1 and 2
cargo run --release -- --p2p 127.0.0.1:6002 --api 127.0.0.1:7002 -c 127.0.0.1:6000 -c 127.0.0.1:6001
# Start mining on all three, then compare their tips — they should match.
for p in 7000 7001 7002; do curl -s "http://127.0.0.1:$p/miner/start?lambda=2000000"; done
for p in 7000 7001 7002; do echo "node $p:"; curl -s "http://127.0.0.1:$p/api/tip"; done
| Endpoint | Description |
|---|---|
GET /miner/start?lambda=<N> | Start mining; lambda sets the inter-block loop delay |
GET /network/ping | Broadcast a ping to connected peers |
GET /api/tip | Current tip hash and height |
GET /api/blocks?start=<h>&end=<h> | Blocks in a height range (hash, parent, height, timestamp, tx count) |
GET /blockchain/length | Total stored block count and tip height |
GET /blockchain/stats | Block/mined/received counts, avg block-propagation delay, avg block size |
GET /blockchain/state | Ledger state: per-address (nonce, balance) |
GET /visualize | Interactive HTML blockchain visualizer |
The /visualize endpoint serves a self-contained web page that polls /api/blocks
and /api/tip to render the chain as a growing graph — the main chain, any forks
and orphaned branches, and per-block metadata (height, timestamp, transaction
count). It updates live while the node mines, making forks and reorgs easy to see.
Because block production rate and network propagation are both configurable, the node doubles as a small testbed for blockchain dynamics:
--difficulty (and the lambda mining
delay) and read mined_count / tip_height from /blockchain/stats to observe
how the expected time-to-block scales with the size of the target space./api/tip. avg_delay_ms in /blockchain/stats reports
mean block-propagation delay; raising the mining rate relative to propagation
delay increases the fork rate, illustrating why real networks tune block time
well above network latency.Rust 2018 · ring (crypto) · mio / mio-extras / net2 (async networking) ·
crossbeam (channels) · serde / bincode / serde_json (serialization) ·
tiny_http (API) · clap (CLI) · ring-backed SHA-256 & Ed25519.
Released under the MIT License.
1 commits
Rust
81.1%
HTML
18.9%