3.4-protocol.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. # Section 3.4 from "Streamlet: Textbook Streamlined Blockchains"
  2. from block import Block
  3. from node import Node
  4. # Genesis block is generated.
  5. genesis_block = Block("⊥", 0, '⊥')
  6. # We create some nodes to participate in the Protocol.
  7. # There are in total n nodes numbered.
  8. node0 = Node(0, "clock", "node_password0", genesis_block)
  9. node1 = Node(1, "clock", "node_password1", genesis_block)
  10. node2 = Node(2, "clock", "node_password2", genesis_block)
  11. node3 = Node(3, "clock", "node_password3", genesis_block)
  12. node4 = Node(4, "clock", "node_password4", genesis_block)
  13. node5 = Node(5, "clock", "node_password5", genesis_block)
  14. nodes = [node0, node1, node2, node3, node4, node5]
  15. # We simulate some rounds to test consistency.
  16. epoch = 1
  17. # Nodes receive transactions and broacasts them between them.
  18. # node0 receives input and broadcasts it to rest nodes.
  19. node0.receive_transaction("tx0")
  20. node0.broadcast_transaction([node1, node2, node3, node4, node5], "tx0")
  21. # node1 receives input and broadcasts it to rest nodes.
  22. node1.receive_transaction("tx2")
  23. node1.broadcast_transaction([node0, node2, node3, node4, node5], "tx2")
  24. # node4 receives input and broadcasts it to rest nodes.
  25. node4.receive_transaction("tx3")
  26. node4.broadcast_transaction([node0, node1, node2, node3, node5], "tx3")
  27. # A random leader is selected.
  28. leader = nodes[hash(str(epoch))%len(nodes)]
  29. # Leader forms a block and broadcasts it.
  30. leader.propose_block(epoch, nodes)
  31. # Nodes vote on the block and broadcast their vote to rest nodes.
  32. for node in nodes:
  33. node.vote_on_round_block(nodes)
  34. # We verify that all nodes have the same blockchain on round end.
  35. assert(node0.output() == node1.output() == node2.output() == node3.output() == node4.output() == node5.output())
  36. epoch = 2
  37. # We introduce a new node. Assumption: no history sync, a Node starts participating in next epoch.
  38. node6 = Node(6, "clock", "node_password5", node0.output()[-1])
  39. nodes.append(node6)
  40. # node3 receives input and broadcasts it to rest nodes.
  41. node3.receive_transaction("tx4")
  42. node3.broadcast_transaction([node0, node1, node2, node4, node5, node6], "tx4")
  43. # node5 receives input and broadcasts it to rest nodes.
  44. node5.receive_transaction("tx5")
  45. node5.broadcast_transaction([node0, node1, node2, node3, node4, node6], "tx5")
  46. # node6 receives input and broadcasts it to rest nodes.
  47. node6.receive_transaction("tx6")
  48. node6.broadcast_transaction([node0, node1, node2, node3, node4, node5], "tx6")
  49. # A random leader is selected.
  50. leader = nodes[hash(str(epoch))%len(nodes)]
  51. # Leader forms a block and broadcasts it.
  52. leader.propose_block(epoch, nodes)
  53. # Nodes vote on the block and broadcast their vote to rest nodes.
  54. for node in nodes:
  55. node.vote_on_round_block(nodes)
  56. # We verify that all nodes have the same blockchain on round end.
  57. assert(node0.output() == node1.output() == node2.output() == node3.output() == node4.output() == node5.output())
  58. # Since node6 joined later, node0 output is a prefix or equal to node6 output.
  59. # Based on that, node6 output is a suffix of node0 output.
  60. assert(node0.output().blocks[-len(node6.output()):] == node6.output().blocks)
  61. print('finished...')