realtonypark/mini-bitcoin

A Bitcoin-style full node and proof-of-work mining simulator written in Rust.

Rust

1

1 commits

updated Jul 17, 2026

See the code

See what people are saying

README

mini-bitcoin

A Bitcoin-style full node and proof-of-work mining simulator, written in Rust.

CI License: MIT 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.


Features

  • Cryptographic primitives — SHA-256 block/transaction hashing and Ed25519 signatures via ring; 32-byte hashes (H256) and 20-byte addresses (H160) derived from public keys.
  • Merkle trees — transactions in each block are committed to a Merkle root in the block header.
  • Proof-of-work mining — a miner thread iterates nonces until a block hash falls below a 256-bit difficulty target; difficulty is configurable at genesis.
  • Longest-chain consensus — fork-choice by longest chain, with an orphan buffer that holds blocks whose parents haven't arrived yet and connects them once the parent is seen.
  • Account-based ledger — a state of (nonce, balance) per address, updated as blocks are applied; transactions are checked for valid signatures, sufficient balance, and correct nonce (double-spend / replay protection).
  • Mempool + transaction generator — pending transactions are pooled and gossiped; a background generator produces a steady stream of signed transactions to keep blocks non-empty.
  • P2P gossip network — a non-blocking 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.
  • REST API + live visualizer — control the miner and inspect chain state over HTTP, and open an interactive D3-style blockchain view in the browser.

Architecture

                    ┌─────────────────────────────────────────┐
                    │           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/):

ModuleResponsibility
crypto/hash (H256/SHA-256), key_pair (Ed25519), address (H160), merkle
block.rsblock/header/content structs, genesis, hashing
blockchain.rsinsertion, longest-chain fork-choice, orphan buffer, ledger state
transaction.rstransaction model, signing & verification
transaction_generator.rsbackground generator of signed transactions
mempool.rspool of pending transactions
miner.rsproof-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

Build

Requires a stable Rust toolchain (rustup).

cargo build --release

Run

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:

FlagDefaultDescription
--p2p <ADDR>127.0.0.1:6000P2P server bind address
--api <ADDR>127.0.0.1:7000HTTP API bind address
-c, --connect <PEER>Peer address(es) to dial on startup (repeatable)
--p2p-workers <N>4Worker threads for the P2P server
--difficulty <HEX>0x0fff…ffGenesis PoW target, 64-char hex (32 bytes, big-endian). Smaller = harder.
-vIncrease 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.

Multi-node demo

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

REST API

EndpointDescription
GET /miner/start?lambda=<N>Start mining; lambda sets the inter-block loop delay
GET /network/pingBroadcast a ping to connected peers
GET /api/tipCurrent tip hash and height
GET /api/blocks?start=<h>&end=<h>Blocks in a height range (hash, parent, height, timestamp, tx count)
GET /blockchain/lengthTotal stored block count and tip height
GET /blockchain/statsBlock/mined/received counts, avg block-propagation delay, avg block size
GET /blockchain/stateLedger state: per-address (nonce, balance)
GET /visualizeInteractive HTML blockchain visualizer

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.

Experiments

Because block production rate and network propagation are both configurable, the node doubles as a small testbed for blockchain dynamics:

  • Mining rate vs. difficulty. Vary --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.
  • Propagation & consistency across nodes. Run the multi-node demo above and compare each node's /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.

Tech stack

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.

License

Released under the MIT License.

Contributors

realtonypark

1 commits

realtonypark/mini-bitcoin

A Bitcoin-style full node and proof-of-work mining simulator written in Rust.

Rust

1

1 commits

updated Jul 17, 2026

See the code

See what people are saying

README

mini-bitcoin

A Bitcoin-style full node and proof-of-work mining simulator, written in Rust.

CI License: MIT 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.


Features

  • Cryptographic primitives — SHA-256 block/transaction hashing and Ed25519 signatures via ring; 32-byte hashes (H256) and 20-byte addresses (H160) derived from public keys.
  • Merkle trees — transactions in each block are committed to a Merkle root in the block header.
  • Proof-of-work mining — a miner thread iterates nonces until a block hash falls below a 256-bit difficulty target; difficulty is configurable at genesis.
  • Longest-chain consensus — fork-choice by longest chain, with an orphan buffer that holds blocks whose parents haven't arrived yet and connects them once the parent is seen.
  • Account-based ledger — a state of (nonce, balance) per address, updated as blocks are applied; transactions are checked for valid signatures, sufficient balance, and correct nonce (double-spend / replay protection).
  • Mempool + transaction generator — pending transactions are pooled and gossiped; a background generator produces a steady stream of signed transactions to keep blocks non-empty.
  • P2P gossip network — a non-blocking 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.
  • REST API + live visualizer — control the miner and inspect chain state over HTTP, and open an interactive D3-style blockchain view in the browser.

Architecture

                    ┌─────────────────────────────────────────┐
                    │           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/):

ModuleResponsibility
crypto/hash (H256/SHA-256), key_pair (Ed25519), address (H160), merkle
block.rsblock/header/content structs, genesis, hashing
blockchain.rsinsertion, longest-chain fork-choice, orphan buffer, ledger state
transaction.rstransaction model, signing & verification
transaction_generator.rsbackground generator of signed transactions
mempool.rspool of pending transactions
miner.rsproof-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

Build

Requires a stable Rust toolchain (rustup).

cargo build --release

Run

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:

FlagDefaultDescription
--p2p <ADDR>127.0.0.1:6000P2P server bind address
--api <ADDR>127.0.0.1:7000HTTP API bind address
-c, --connect <PEER>Peer address(es) to dial on startup (repeatable)
--p2p-workers <N>4Worker threads for the P2P server
--difficulty <HEX>0x0fff…ffGenesis PoW target, 64-char hex (32 bytes, big-endian). Smaller = harder.
-vIncrease 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.

Multi-node demo

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

REST API

EndpointDescription
GET /miner/start?lambda=<N>Start mining; lambda sets the inter-block loop delay
GET /network/pingBroadcast a ping to connected peers
GET /api/tipCurrent tip hash and height
GET /api/blocks?start=<h>&end=<h>Blocks in a height range (hash, parent, height, timestamp, tx count)
GET /blockchain/lengthTotal stored block count and tip height
GET /blockchain/statsBlock/mined/received counts, avg block-propagation delay, avg block size
GET /blockchain/stateLedger state: per-address (nonce, balance)
GET /visualizeInteractive HTML blockchain visualizer

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.

Experiments

Because block production rate and network propagation are both configurable, the node doubles as a small testbed for blockchain dynamics:

  • Mining rate vs. difficulty. Vary --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.
  • Propagation & consistency across nodes. Run the multi-node demo above and compare each node's /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.

Tech stack

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.

License

Released under the MIT License.

Contributors

realtonypark

1 commits

Languages

Rust

81.1%

HTML

18.9%