blockchain-access-control

git clone git://git.codymlewis.com/blockchain-access-control.git
Log | Files | Refs | README

Blockchain.py (3110B)


      1 #!/usr/bin/env python3
      2 # -*- coding: utf-8 -*-
      3 
      4 '''
      5 A simple blockchain implementation
      6 Based on the original bitcoin and the example from
      7 https://developer.ibm.com/technologies/blockchain/tutorials/develop-a-blockchain-application-from-scratch-in-python/
      8 '''
      9 
     10 from hashlib import sha256
     11 import json
     12 import time
     13 
     14 class Block:
     15     "A single block that holds some data as a transaction"
     16     def __init__(self, index, transactions, timestamp, previous_hash):
     17         '''
     18         Create a block
     19         :param index: ID of the block
     20         :param transactions: data stored in the block
     21         :param timestamp: Time block was created
     22         :param previous_hash: hash of the previous block
     23         '''
     24         self.index = index
     25         self.transactions = transactions
     26         self.timestamp = timestamp
     27         self.previous_hash = previous_hash
     28 
     29     def compute_hash(self):
     30         '''
     31         Compute the hash of this block
     32         '''
     33         b = json.dumps(self.__dict__, sort_keys=True)
     34         return sha256(b.encode()).hexdigest()
     35 
     36 
     37 class Blockchain:
     38     "A chain of immutable blocks"
     39     def __init__(self, difficulty=2):
     40         '''
     41         Create the blockchain
     42         :param difficulty: Difficulty in perform the PoW
     43         '''
     44         b = Block(0, "", time.time(), "0")
     45         b.hash = b.compute_hash()
     46         self.chain = [b]
     47         self.difficulty = difficulty
     48 
     49     def proof_of_work(self, block):
     50         '''
     51         Prove that computational work was spent in creating the block
     52         :param block: The block to prove
     53         '''
     54         block.nonce = 0
     55         computed_hash = block.compute_hash()
     56         while not computed_hash.startswith("0" * self.difficulty):
     57             block.nonce += 1
     58             computed_hash = block.compute_hash()
     59         return computed_hash
     60 
     61     def add_block(self, block, proof):
     62         '''
     63         Add a block to the chain if its proof is valid
     64         :param block: Block to add
     65         :param proof: Proof of work in adding the block
     66         '''
     67         previous_hash = self.last_block.hash
     68         if previous_hash != block.previous_hash:
     69             return False
     70         if not self.is_valid_proof(block, proof):
     71             return False
     72         block.hash = proof
     73         self.chain.append(block)
     74         return True
     75 
     76     def is_valid_proof(self, block, proof):
     77         '''
     78         Check whether a proof is valid
     79         :param block: Block to check
     80         :param proof: proof to check against the block
     81         '''
     82         return (proof.startswith("0" * self.difficulty)) and \
     83             (proof == block.compute_hash())
     84 
     85     def mine(self, transactions):
     86         '''
     87         Perfom computational work to add data to the chain
     88         '''
     89         b = Block(
     90             self.last_block.index + 1,
     91             transactions,
     92             time.time(),
     93             self.last_block.hash
     94         )
     95         p = self.proof_of_work(b)
     96         self.add_block(b, p)
     97         self.unconfirmed_trans = []
     98         return True
     99 
    100     @property
    101     def last_block(self):
    102         '''
    103         Get the last block in the chain
    104         '''
    105         return self.chain[-1]