Skip to content

Education project that demonstrates a minimal blockchain with Proof of Work and a small HTTP API using Flask

Notifications You must be signed in to change notification settings

lopescode/generic-blockchain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Generic Blockchain

Educational project demonstrating a minimal blockchain with Proof of Work and an HTTP API using Flask. The project supports running multiple nodes (e.g., ports 5000, 5001, 5002) from a shared app factory without duplicating code.

Overview

  • Simple blockchain in Python (src/blockchain.py).
  • Reusable Flask app factory (src/app_factory.py) to avoid code duplication.
  • CLI runner (src/serve_chain.py) to start a node on any port.
  • REST endpoints:
    • GET /mine_block
    • GET /get_chain
    • GET /is_valid
    • POST /add_transaction
    • POST /connect_node
    • GET /replace_chain
  • Basic Proof of Work: valid hashes start with 0000.

Tech Stack

  • Python 3.x
  • Flask (HTTP API)
  • hashlib (SHA-256)
  • json
  • requests (for node-to-node communication)
  • urllib.parse (for URL parsing)

Requirements

  • Python 3.10+
  • pip
  • Optional: Python virtual environment (venv)

Recommended requirements.txt

Setup

Create and activate a virtual environment (optional), then install dependencies.

  • Create venv (PowerShell):
  python -m venv venv
  • Activate venv (PowerShell):
  .\venv\Scripts\activate

Install dependencies

pip install -r requirements.txt

Run Multiple Nodes

Start three nodes in separate terminals using different ports:

  • Port 5000:
  python src/serve_chain.py --port 5000
  • Port 5001:
  python src/serve_chain.py --port 5001
  • Port 5002:
  python src/serve_chain.py --port 5002

Connect Nodes

Connect node 5000 to 5001 and 5002:

curl -X POST http://localhost:5000/connect_node -H "Content-Type: application/json" -d "{"nodes": ["127.0.0.1:5001", "127.0.0.1:5002"]}"

Replace the chain with the longest one (trigger consensus):

curl -X GET http://localhost:5000/replace_chain

API

Mine Block

  • Method: GET
  • URL: /mine_block
  • Response 200 OK:
{
  "message": "Block mined!",
  "index": 2,
  "timestamp": "2025-01-01 12:34:56.789012",
  "proof": 533,
  "previous_hash": "0000ab12...",
  "transactions": [
    {
      "sender": "node_address",
      "receiver": "Lopes",
      "amount": 10
    }
  ]
}

Get Chain

  • Method: GET
  • URL: /get_chain
  • Response 200 OK:
{
  "chain": [
    {
      "index": 1,
      "timestamp": "2025-01-01 12:00:00.000000",
      "proof": 1,
      "previous_hash": "0",
      "transactions": []
    }
  ],
  "length": 1
}

Is Valid

  • Method: GET
  • URL: /is_valid
  • Response 200 OK:
{ "message": "All good. The Blockchain is valid." }

Add Transaction

  • Method: POST
  • URL: /add_transaction
  • Body (JSON):
{ "sender": "node_1", "receiver": "node_2", "amount": 10 }
  • Response 201 Created:
{ "message": "This transaction will be added to Block 2" }

Connect Node

  • Method: POST
  • URL: /connect_node
  • Body (JSON):
{ "nodes": ["127.0.0.1:5001", "127.0.0.1:5002"] }
  • Response 201 Created:
{
  "message": "All nodes are now connected. The chain now contains the following nodes:",
  "total_nodes": ["127.0.0.1:5001", "127.0.0.1:5002"]
}

Replace Chain

  • Method: GET
  • URL: /replace_chain
  • Response 200 OK:
{
  "message": "The nodes had different chains so the chain was replaced by the longest one.",
  "new_chain": [
    /* ... */
  ]
}

Templates

  • templates/transactions.json
{
  "sender": "node_1",
  "receiver": "node_2",
  "amount": 10
}
  • templates/nodes.json
{
  "nodes": ["127.0.0.1:5001", "127.0.0.1:5002"]
}

How It Works

  • create_block(proof, previous_hash): Builds and appends a block with index, timestamp, proof, previous hash, and pending transactions; clears pending transactions.
  • proof_of_work(previous_proof): Finds new_proof such that SHA256(str(new_proof**2 - previous_proof**2)) starts with 0000.
  • hash(block): Computes SHA-256 over a JSON-serialized block (sort_keys=True).
  • is_chain_valid(chain): Checks chain linkage and PoW validity.
  • add_transaction(sender, receiver, amount): Queues a transaction for the next mined block.
  • add_node(address): Adds a node (expects host:port).
  • replace_chain(): Fetches chains from connected nodes and replaces the local chain with the longest valid one.

Disclaimer

This project is for learning purposes only and is not production-ready. It lacks security features, P2P networking, persistence, and robust distributed consensus.

About

Education project that demonstrates a minimal blockchain with Proof of Work and a small HTTP API using Flask

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages