block.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import json
  2. from utils import encode_genesis_data, decode_gensis_data, state_hash
  3. '''
  4. single block B_i for slot i in the system live time L,
  5. assigned to stakeholder U_j, with propability P_j_i,
  6. in the chain C, should be signed by U_j keys.
  7. '''
  8. class Block(object):
  9. '''
  10. @param previous_block: parent block to the current block
  11. @param data: is the transaction, or contracts in the leadger, or gensis block data,
  12. data is expected to be binary, no format is enforced
  13. @param slot_uid: the block corresponding slot monotonically increasing index,
  14. it's one-based
  15. @param gensis: boolean, True for gensis block
  16. '''
  17. def __init__(self, previous_block, data, slot_uid, genesis=False):
  18. # state is hte hash of the previous block in the blockchain
  19. self.state=''
  20. if slot_uid>1:
  21. self.state=state_hash(previous_block)
  22. self.tx = data
  23. self.sl = slot_uid
  24. self.is_genesis=genesis
  25. def __repr__(self):
  26. if self.is_genesis:
  27. return "GensisBlock at {slot:"+self.sl+",data:"+self.tx+",state:"+self.state+"}\n"+\
  28. decode_gensis_data(self.data)
  29. return "Block at {slot:"+self.sl+",data:"+self.tx+",state:"+self.state+"}"
  30. def __eq__(self, block):
  31. return self.state==block.state and \
  32. self.tx == block.tx and \
  33. self.sl == block.sl
  34. def to_json(self):
  35. d = {'state':self.state, \
  36. 'data': self.tx, \
  37. 'sl': self.sl}
  38. return json.encoder(d)
  39. @property
  40. def state(self):
  41. return self.st
  42. @property
  43. def data(self):
  44. return self.tx
  45. @property
  46. def slot(self):
  47. return self.sl
  48. @property
  49. def empty(self):
  50. return (self.data=='' or self.slot<0) and self.state==''
  51. class GensisBlock(Block):
  52. '''
  53. @param data: data is dictionary of list of (pk_i, s_i) public key,
  54. and stake respectively of the corresponding stakeholder U_i,
  55. seed of the leader election function.
  56. '''
  57. def __init__(self, previous_block, data, slot_uid):
  58. # stakeholders is list of tuple (pk_i, s_i) for the ith stakeholder
  59. self.stakeholders = data['stakeholders']
  60. self.seed = data['seed']
  61. data = encode_genesis_data(self.stakeholders, self.seed)
  62. super.__init__(previous_block, data, slot_uid, True)
  63. '''
  64. @return: the number of participating stakeholders in the blockchain
  65. '''
  66. @property
  67. def length(self):
  68. return len(self.stakeholders)
  69. def __getitem__(self, i):
  70. if i<0 or i>=self.length:
  71. raise "index is out of range!"
  72. return self.stakeholders[i]
  73. '''
  74. block lead by an adversary, or
  75. lead by offline leader
  76. is an empty Block
  77. '''
  78. class EmptyBlock(Block):
  79. def __init__(self):
  80. super.__init__(None, '', -1, False)