3.2-blocks-and-blockchain.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. # Section 3.2 from "Streamlet: Textbook Streamlined Blockchains"
  2. class Block:
  3. ''' This class represents a tuple of the form (h, e, txs).
  4. Each blocks parent hash h may be computed simply as a hash of the parent block. '''
  5. def __init__(self, h, e, txs):
  6. self.h = h # parent hash
  7. self.e = e # epoch number
  8. self.txs = txs # transactions payload
  9. def __repr__(self):
  10. return "Block=[h={0}, e={1}, txs={2}]".format(self.h, self.e, self.txs)
  11. def __hash__(self):
  12. return hash((self.h, self.e, self.txs)) # Python hash is used for demostranation porpuses only.
  13. class Blockchain:
  14. ''' This class represents a sequence of blocks starting with the genesis block. '''
  15. def __init__(self, genesis_block):
  16. self.chain = [genesis_block]
  17. def __repr__(self):
  18. return "Blockchain=[chain={0}]".format(self.chain)
  19. def check_block_validity(self, block, previous_block):
  20. ''' A block is considered valid when its parent hash is equal to the hash of the
  21. previous block and their epochs are incremental, exluding genesis. '''
  22. assert(block.h != '⊥') # genesis block check
  23. assert(block.h == hash(previous_block))
  24. assert(block.e > previous_block.e)
  25. def check_chain_validity(self):
  26. ''' A blockchain is considered valid, when every block is valid, based on check_block_validity method. '''
  27. for index, block in enumerate(self.chain[1:]):
  28. self.check_block_validity(block, self.chain[index])
  29. def add_block(self, block):
  30. ''' Insertion of a valid block. '''
  31. self.check_block_validity(block, self.chain[-1])
  32. self.chain.append(block)
  33. # We generate a genesis block and a blockchain.
  34. genesis_block = Block("⊥", 0, '⊥')
  35. chain = Blockchain(genesis_block)
  36. # A new block is generated and appended to the blockchain, since its valid.
  37. block1 = Block(hash(genesis_block), 1, "tx1, tx2, tx3")
  38. chain.add_block(block1)
  39. # A new block is generated and appended to the blockchain, since its valid.
  40. block2 = Block(hash(block1), 2, "tx4, tx5, tx6")
  41. chain.add_block(block2)
  42. # We check entire blockchain validity.
  43. chain.check_chain_validity()
  44. # Following code examples will fail, due to block validity checks:
  45. # wrong_block = Block(hash(block1), 3, "tx4,tx5,tx6") # Previous block not last.
  46. # chain.add_block(wrong_block)
  47. # wrong_block = Block(hash(block2), 1, "tx4,tx5,tx6") # Epoch not incremental.
  48. # chain.add_block(wrong_block)