Built a proof-of-work blockchain from scratch in Rust โ€” nodes, wallets, P2P sync, CLI

โš“ Rust    ๐Ÿ“… 2026-05-31    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 1      

surdeus

Been working on this for a while and finally got it to a state I'm happy with. It's called KamiChain โ€” a minimal but complete PoW blockchain built entirely in Rust with no blockchain libraries, just the primitives.

What's in it:

  • kamichain-core โ€” the chain itself. SHA-256 block hashing, Merkle tree for tx integrity, parallel PoW mining using Rayon (splits the nonce space across cores with find_any), ed25519 transaction signing

  • kamichain-node โ€” a running node with a mempool, async RPC over TCP (newline-delimited JSON), P2P gossip, chain persistence with atomic file writes, and longest-chain fork resolution

  • kamichain-wallet โ€” ed25519 keypairs, signing, verification

  • kamichain-cli โ€” a kami binary to interact with nodes (kami wallet new, kami tx send, kami chain info, kami node start, etc.)

The parallel mining was the most interesting part to figure out. The problem is you can't hand &mut Block to multiple threads โ€” the borrow checker won't allow it. Solution: snapshot the immutable fields, search nonce ranges in parallel with Rayon's into_par_iter().find_any(), write the winning nonce back once. The speedup depends on core count and difficulty โ€” at difficulty 4 it's noticeable.

Other things I had to think through:

  • Arc<RwLock> shared between the miner loop, RPC server, and P2P layer โ€” getting the lock boundaries right so reads don't block writes unnecessarily

  • Mempool balance validation the mempool checks amount + fee <= sender_balance at admission time so the miner never picks up underfunded transactions. But each tx is checked against the current on-chain balance independently, so two pending txs from the same sender can both pass even if together they'd overdraw. Miner catches this at block commit time.

  • Transaction uniqueness โ€” originally I was hashing sender + recipient + amount for the tx ID which means aliceโ†’bob for 10 twice produces the same ID and the second looks like a duplicate. Fixed by adding a random u64 nonce to the hash.

About 170 tests across all crates. Criterion benchmarks for block hashing, Merkle root, PoW, and chain validation.

Repo: GitHub - Joshuaisikah/kamichain ยท GitHub

Would love any feedback on the architecture, especially around the P2P and locking story โ€” I kept it simple (one message per TCP connection, no persistent peers) but I know there are production tradeoffs there.

1 post - 1 participant

Read full topic

๐Ÿท๏ธ Rust_feed