A educational, single-file C program that simulates a simplified blockchain network: transactions, Merkle trees, Proof-of-Work mining, a multi-node P2P consensus mechanism (via POSIX threads), and integrity verification / tamper detection.
!! This is a learning project, not a production or cryptographically secure implementation. The hashing function is a custom, simplified avalanche-style hash — not real SHA-256.
- Transactions — sender, receiver, amount, timestamp, and a hash for integrity.
- Merkle Tree — combines all transaction hashes in a block into a single Merkle root, so any tampering with a transaction is detectable.
- Proof of Work (PoW) — each block is "mined" by searching for a
noncesuch that the block's hash starts withDIFFICULTYleading zeros. - Multi-node network simulation —
MAX_NODESthreads act as independent nodes, each holding its own copy of the chain. - Consensus mechanism — a new block is broadcast to all nodes; each node independently validates it (PoW, hash correctness, chain linkage, Merkle root) and votes; the block is accepted only by majority vote.
- Chain integrity verification — walks the whole chain and recomputes hashes/Merkle roots to detect corruption.
- Tampering demo — shows what happens when a transaction amount is modified after the fact without recomputing hashes (fraud detection in action).
- Invalid block rejection demo — broadcasts a block with a forged
prev_hashand shows the network rejecting it.
Everything lives in a single C source file, organized into clearly labeled parts:
| Section | Content |
|---|---|
| Part 1 | Data structures: Transaction, Block, Blockchain, Node |
| Part 2A | Hashing (simple_hash, hash_transaction) |
| Part 2B | Merkle tree computation (compute_merkle_root) |
| Part 2C | Block hashing & Proof of Work (compute_block_hash, mine_block, meets_difficulty) |
| Init | Blockchain/genesis block setup (init_blockchain) |
| Part 3 | Threaded node simulation (node_thread_func), transaction round coordination |
| Part 4 | Consensus / block broadcasting (broadcast_block) |
| Verification | Full chain integrity check (verify_chain_integrity) |
| Display | Pretty-printing helpers (print_block, print_blockchain) |
| Part 5 | Tampering demo, main() driving the full simulation |
| Constant | Meaning | Default |
|---|---|---|
MAX_TRANSACTIONS |
Max transactions per block | 10 |
HASH_SIZE |
Hash string length (hex + \0) |
65 |
MAX_NODES |
Number of simulated network nodes (threads) | 3 |
DIFFICULTY |
Required leading zeros for PoW | 3 |
MAX_BLOCKS |
Max blocks a chain can hold | 100 |
ADDR_SIZE |
Max length of an address string (e.g. "Alice") | 20 |
-
Network startup —
MAX_NODESthreads are launched. Node 0 creates the blockchain and mines the Genesis Block. Other nodes synchronize by copying node 0's chain. -
Transaction rounds — the main thread signals a "round" of transactions; each node creates its assigned transaction(s) for that round.
-
Block creation — the collected transactions are placed into a new block, a Merkle root is computed, and the block is mined (PoW) to find a valid nonce.
-
Broadcast & consensus — the mined block is broadcast to the network. Each node independently validates:
- PoW difficulty is met
- Recomputed block hash matches the stored hash
prev_hashcorrectly chains to the node's last block- Merkle root matches the transactions
Nodes vote, and the block is accepted only if a strict majority votes yes.
-
Integrity check — the full chain is re-verified block by block.
-
Fraud simulation — a transaction amount is silently altered in an already-mined block (hashes not recalculated), and
verify_chain_integrity()catches the corruption. -
Invalid block rejection — a block with a forged
prev_hashis broadcast and correctly rejected by consensus. -
Consistency check — all nodes' chain lengths and final hashes are compared to confirm the network stayed in sync.
-
Shutdown — all node threads are stopped and joined cleanly.
Requires a C compiler with POSIX threads support (Linux/macOS, or WSL on Windows).
gcc -o blockchain blockchain.c -lpthread -Wall./blockchainThe program prints the full simulation trace to stdout: node startup, mining progress, consensus voting, the printed blockchain, integrity checks, and both the tampering and invalid-block demos.
simple_hash()is a custom pseudo-hash (djb2/FNV-style mixing), not a cryptographic algorithm — it's meant to demonstrate avalanche effect and hashing concepts, not for real security use.- The network simulation uses polling (
usleep+ shared flags) rather than real message passing — fine for a teaching demo, not representative of real P2P networking. - Fixed-size arrays (
MAX_BLOCKS,MAX_TRANSACTIONS,MAX_NODES) mean the simulation is capped in scale; there's no dynamic chain growth beyondMAX_BLOCKS. - No persistence — the entire chain lives in memory and is lost when the program exits.
This project is a good hands-on illustration of:
- Why blockchains are tamper-evident (hash chaining + Merkle trees)
- What Proof of Work actually computes and why it's asymmetric (hard to find, easy to verify)
- How distributed consensus/majority voting can reject fraudulent blocks
- Practical use of POSIX threads and mutexes for shared-state simulation