Overview
A blockchain node in a single Python file. Flask exposes each node over HTTP, and several nodes on the same network keep one ledger in agreement. It was built to understand the moving parts of a chain, not to hold value.
Blocks and hashing
Each block is a JSON object:
{
"index": 2,
"timestamp": 1712912345.1,
"transactions": [{ "sender": "0", "recipient": "9f2c…", "amount": 1 }],
"proof": 35293,
"previous_hash": "a3f1…"
}
A block’s hash is SHA-256 over its JSON with sorted keys, so the same block hashes identically on every machine. Each block stores the hash of the one before it. Editing any past block changes its hash and breaks every link that follows. The genesis block is created with a fixed proof of 100.
Transactions and the mempool
POST /transactions/new checks that sender, recipient and amount are present, adds the transaction to the mempool, and replies with the index of the block it will land in. Mining drains the whole mempool into the next block.
Mining
Proof of work searches for an integer proof where sha256(last_proof + proof) starts with four hex zeros, about 65,536 attempts on average. GET /mine runs that search, adds a coinbase transaction (sender 0, reward 1) paying the node’s UUID, and forges the block with the previous block’s hash.
Networking and consensus
Nodes listen on 0.0.0.0:3245, so any machine on the same Wi-Fi can reach them. POST /nodes/register adds peers. GET /nodes/resolve fetches /chain from every peer and validates each candidate: every previous_hash must match the recomputed hash of the block before it, and every proof must satisfy the puzzle. The node then adopts the longest valid chain. It was tested with nodes on separate physical machines on the same network.
| Endpoint | Does |
|---|---|
GET /chain | Full chain and its length |
POST /transactions/new | Queue a transaction in the mempool |
GET /mine | Run proof of work and forge a block |
POST /nodes/register | Add peer addresses |
GET /nodes/resolve | Adopt the longest valid chain among peers |
Limits
- Transactions are unsigned and balances are not checked. A real chain signs each transaction with the sender’s key and rejects overspends.
- The puzzle depends only on the previous proof, not on the block’s contents, so the work is not bound to the data. Bitcoin-style chains hash the block header, including the transaction root and a nonce, against a difficulty target.
- Consensus runs when a node asks for it, and transactions are not gossiped between peers.