aggstam пре 4 година
родитељ
комит
564e63dfaa

+ 114 - 0
script/research/streamlet/2-execution-model-and-definitions.py

@@ -0,0 +1,114 @@
+# Section 2 from "Streamlet: Textbook Streamlined Blockchains"
+
+class Node:
+	''' This class represents a simplyfied protocol node.
+		Each node is numbered and has a secret-public keys pair, to sign messages. 
+		Modes receive inputs (transactions) and maintain an ordered log (blockchain), 
+		containing a sequense of strings (blocks). '''
+	def __init__(self, id, secret_key, public_key):
+		self.id = id
+		self.secret_key = secret_key
+		self.public_key = public_key
+		self.blockchain = Blockchain()
+		self.inputs = []
+	
+	def __repr__(self):
+		return "Node=[id={0}, secret_key={1}, public_key={2}]".format(self.id, self.secret_key, self.public_key)
+		
+	def receive_input(self, input):
+		# Additional validity rules must be defined by the protocol for its blockchain data structure.
+		self.inputs.append(input)
+	
+	def output(self):
+		return self.blockchain
+	
+	def broadcast(self, nodes, input):
+		for node in nodes:
+			node.receive_input(input)
+			
+	def finalize_block(self):
+		block = Block(self.inputs)
+		self.blockchain.add_block(block) # Block is appended to nodes blockchain
+		self.inputs = []
+		
+class Block:
+	''' This class represents a simplyfied block structure. '''
+	def __init__(self, transactions):
+		self.transactions = transactions
+	
+	def __repr__(self):
+		return "Block=[transactions={0}]".format(self.transactions)
+	
+	def __eq__(self, other):
+		return self.transactions == other.transactions
+		
+class Blockchain:
+	''' This class represents a simplyfied blockchain structure. '''
+	def __init__(self):
+		self.blocks = []
+	
+	def __repr__(self):
+		return "Blockchain=[blocks={0}]".format(self.blocks)
+	
+	def __eq__(self, other):
+		return self.blocks == other.blocks
+		
+	def __len__(self):
+		return len(self.blocks)
+		
+	def __getitem__(self, index):
+          return self.blocks[index]
+	
+	def add_block(self, block):
+		self.blocks.append(block)
+
+# There are in total n nodes numbered.
+node0 = Node(0, "dummy_secret_key0", "dummy_public_key0")
+node1 = Node(1, "dummy_secret_key1", "dummy_public_key1")
+
+# Advesary chooses last node to corrupt(static corruption).
+corruptedNode = Node(2, "dummy_secret_key2", "dummy_public_key2")
+
+# We simulate some rounds to test consistency.
+
+# Round 0 synchronization period
+# node0 receives input and broadcasts it to rest nodes.
+node0.receive_input("tx0")
+node0.broadcast([node1, corruptedNode], "tx0")
+
+# node1 receives input and broadcasts it to rest nodes.
+node1.receive_input("tx1")
+node1.broadcast([node0, corruptedNode], "tx1")
+
+# corruptedNode receives input but doesn't broadcast to rest nodes.
+corruptedNode.receive_input("tx2")
+
+# We assume nodes finalize blocks(append to blockchain) at the end of each round
+node0.finalize_block()
+node1.finalize_block()
+corruptedNode.finalize_block()
+
+# In round 1, a new node joins
+node3 = Node(3, "dummy_secret_key3", "dummy_public_key3")
+
+# node3 receives input and broadcasts it to rest nodes.
+node3.receive_input("tx3")
+node3.broadcast([node0, node1, corruptedNode], "tx3")
+
+# Nodes finalize blocks
+node0.finalize_block()
+node1.finalize_block()
+corruptedNode.finalize_block()
+node3.finalize_block()
+
+# Consistency testing
+# node0 and node1 remained honest, therefore their outputs must be the same
+assert(node0.output() == node1.output())
+
+# Since node3 joined later, node0 and node1 outputs are a prefix or equal to his output.
+# Based on that, node3 output is a suffix of node0 and node1 outputs.
+assert(node0.output()[-len(node3.output()):] == node3.output().blocks)
+assert(node1.output()[-len(node3.output()):] == node3.output().blocks)
+
+# Below assertion will fail, as corrupt node deviated from the protocol.
+# assert(node0.output() == corruptedNode.output())

+ 2 - 2
script/research/streamlet/3.2-blocks-and-blockchain.py

@@ -56,8 +56,8 @@ chain.add_block(block2)
 chain.check_chain_validity()
 
 # Following code examples will fail, due to block validity checks:
-# wrong_block = Block(hash(block1), 3, "tx4,tx5,tx6")
+# wrong_block = Block(hash(block1), 3, "tx4,tx5,tx6") # Previous block not last
 # chain.add_block(wrong_block)
 
-# wrong_block = Block(hash(block1), 1, "tx4,tx5,tx6") # Epoch not incremental
+# wrong_block = Block(hash(block2), 1, "tx4,tx5,tx6") # Epoch not incremental
 # chain.add_block(wrong_block)