Created
December 29, 2025 11:40
-
-
Save ruthlessfish/1042a63bf79128b83680d0b9efe283d9 to your computer and use it in GitHub Desktop.
simple blockchain implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import hashlib | |
| import json | |
| from textwrap import dedent | |
| from time import time | |
| from uuid import uuid4 | |
| from flask import Flask | |
| class Blockchain(object): | |
| def __init__(self): | |
| self.chain = [] | |
| self.current_transactions = [] | |
| self.new_block(previous_hash=1, proof=100) | |
| def new_block(self, proof, previous_hash=None): | |
| """ | |
| Create a new Block in the Blockchain | |
| :param proof: <int> The proof given by the Proof of Work algorithm | |
| :param previous_hash: (Optional) <str> Hash of previous Block | |
| :return: <dict> New Block | |
| """ | |
| block = { | |
| 'index': len(self.chain) + 1, | |
| 'timestamp': time(), | |
| 'transactions': self.current_transactions, | |
| 'proof': proof, | |
| 'previous_hash': previous_hash or self.hash(self.chain[-1]), | |
| } | |
| self.current_transactions = [] | |
| self.chain.append(block) | |
| return block | |
| def new_transaction(self, sender, recipient, amount): | |
| """ | |
| Creates a new transaction to go into the next mined Block | |
| :param sender: <str> Address of the Sender | |
| :param recipient: <str> Address of the Recipient | |
| :param amount: <int> Amount | |
| :return: <int> The index of the Block that will hold this transaction | |
| """ | |
| self.current_transactions.append([ | |
| 'sender': sender, | |
| 'recipient': recipient, | |
| 'amount': amount | |
| ]) | |
| return self.last_block['index'] + 1 | |
| def proof_of_work(self, last_proof): | |
| """ | |
| Simple Proof of Work Algorithm: | |
| - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p' | |
| - p is the previous proof, and p' is the new proof | |
| :param last_proof: <int> | |
| :return: <int> | |
| """ | |
| proof = 0 | |
| while self.valid_proof(last_proof, proof) is False: | |
| proof += 1 | |
| return proof | |
| @property | |
| def last_block(self): | |
| return self.chain[-1]a | |
| @staticmethod | |
| def hash(block): | |
| """ | |
| Creates a SHA-256 hash of a Block | |
| :param block: <dict> Block | |
| :return: <str> | |
| """ | |
| # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes | |
| block_string = json.dumps(block, sort_keys=True).encode() | |
| return hashlib.sha256(block_string).hexdigest() | |
| @staticmethod | |
| def valid_proof(last_proof, proof): | |
| """ | |
| Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes? | |
| :param last_proof: <int> Previous Proof | |
| :param proof: <int> Current Proof | |
| :return: <bool> True if correct, False if not. | |
| """ | |
| guess = f'{last_proof}{proof}'.encode() | |
| guess_hash = hashlib.sha256(guess).hexdigest() | |
| return guess_hash[:4] == "0000" | |
| # Instantiate our Node | |
| app = Flask(__name__) | |
| # Generate a globally unqiuqe address for this node | |
| node_identifier = str(uuid4()).replace('-', '') | |
| # Instantiate the Blockchain | |
| blockchain = Blockchain() | |
| @app.route('/mine', methods=['GET']) | |
| def mine(): | |
| return "We'll mine a new Block" | |
| @app.route('/transactions/new', methods=['POST']) | |
| def new_transaction(): | |
| return "We'll add a new transaction" | |
| @app.route('/chain', methods=['GET']) | |
| def full_chain(): | |
| response = { | |
| 'chain': blockchain.chain, | |
| 'length': len(blockchain.chain) | |
| } | |
| return jsonify(response), 200 | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=5000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment