def handle_message(type, message, sender): """ Used to handle an incoming message sent by another node (heh-heh-heyyyy!). Args: type (str): Type of message to process as; unknown types are ignored. message (str): Payload to deliver to subcomponent based on type. sender (str): Sender of message (primarily used to find key in PKI). """ print("SENDER", sender) if type == "addblock": # Add block to blockchain block = string_to_block(message) from blockchain import chaindb chaindb.connection.close() chaindb.db.close() importlib.reload(chaindb) chain = chaindb.chain print(block) print(block.is_valid()) if not block.hash in chain.blocks and block.is_valid(): # if it's a valid block we haven't seen, retransmit chain.add_block(block) gossip_message(type, message) chaindb.connection.close() chaindb.db.close() if type == "synchrony-start": # Kick off the round-based synchrony tracker if not synchrony.is_started(): synchrony.receive_start_message() gossip_message(type, "") if type == "ba-start": # Kick off the BA protocol if config.ba == None: from byzantine_agreement.simple_ba import SimplePKIBA from byzantine_agreement.byzantine_ba import ByzantineSimplePKIBA if not config.node_id in config.BYZANTINE_NODES: config.ba = SimplePKIBA(int(message)) else: config.ba = ByzantineSimplePKIBA(int(message)) gossip_message(type, message) if type == "ba-vote": # Send confirmed vote to our BA protocol config.ba.process_vote(message)
def test_ba_proposals(self): SimplePKIBA.run_protocol_loop = lambda x: x # disable protocol loop to prevent hanging thread curr_ba = SimplePKIBA(1) import config config.node_id = 4 self.assertEqual(curr_ba.calculate_votes_for(0), []) self.assertEqual(curr_ba.calculate_votes_for(1000), []) self.assertEqual(curr_ba.calculate_votes_for(-1), []) # check that relevant data stuctures are still empty self.assertEqual(curr_ba.s_i, []) self.assertEqual(curr_ba.votes, {}) self.assertEqual(curr_ba.signatures, {}) # single proposal, some votes self.reset_ba(curr_ba) # mock in votes and signatures curr_ba.votes = {"hi": set([1, 2])} curr_ba.signatures = {"hi": [(1, "a"), (2, "b")]} self.assertEqual( curr_ba.calculate_votes_for(0), ['hi']) # hi should be added to S_i here (reaches vote threshold) # ensure data structures are correctly updated self.assertEqual(curr_ba.s_i, ['hi']) self.assertEqual(curr_ba.votes['hi'], set([1, 2, 4])) self.assertEqual(set([x[0] for x in curr_ba.signatures['hi']]), set([1, 2, 4])) self.assertEqual(curr_ba.calculate_votes_for(1), []) self.assertEqual(curr_ba.calculate_votes_for(2), []) self.assertEqual(curr_ba.calculate_votes_for(3), []) self.assertEqual(curr_ba.calculate_votes_for(-1), []) self.assertEqual(curr_ba.calculate_votes_for(100), []) self.assertEqual(curr_ba.s_i, ['hi']) self.assertEqual(curr_ba.votes['hi'], set([1, 2, 4])) self.assertEqual(set([x[0] for x in curr_ba.signatures['hi']]), set([1, 2, 4])) # single proposal, no votes self.reset_ba(curr_ba) curr_ba.votes = {"hi": set([])} curr_ba.signatures = {"hi": []} self.assertEqual(curr_ba.calculate_votes_for(100), []) self.assertEqual(curr_ba.calculate_votes_for(0), []) # multi proposal, mixed votes self.reset_ba(curr_ba) curr_ba.votes = { "hi": set([1, 2, 3, 4]), "a": set([1, 2]), "64": set([6]) } curr_ba.signatures = { "hi": [(1, "a"), (2, "b"), (3, "c"), (4, "d")], "a": [(1, "a"), (2, "b")], "64": [6, "z"] } # ensure data structures are correctly updated self.assertEqual(set(curr_ba.calculate_votes_for(0)), set(["hi", "a"])) self.assertEqual(set(curr_ba.calculate_votes_for(1)), set([])) self.assertEqual(curr_ba.calculate_votes_for(3), []) self.assertEqual(curr_ba.calculate_votes_for(10), [])
def test_ba_output(self): SimplePKIBA.run_protocol_loop = lambda x: x # disable protocol loop to prevent hanging thread curr_ba = SimplePKIBA(1) # Check that if done is False, no output is returned regardless of s_i # (no matter what, this should be None) curr_ba.is_done = lambda: False curr_ba.s_i = [1] self.assertEqual(curr_ba.get_output(), None) curr_ba.s_i = [] self.assertEqual(curr_ba.get_output(), None) curr_ba.s_i = [1, 2] self.assertEqual(curr_ba.get_output(), None) # Check that if done is True, correct output is returned regardless of s_i curr_ba.is_done = lambda: True curr_ba.s_i = [1] self.assertEqual(curr_ba.get_output(), 1) curr_ba.s_i = [] self.assertEqual(curr_ba.get_output(), 0) # no elements in s_i; output 0 curr_ba.s_i = [1, 2] self.assertEqual( curr_ba.get_output(), 0) # multiple elements in s_i (Byzantine sender); output 0
def test_ba_proposals(self): SimplePKIBA.run_protocol_loop = lambda x : x # disable protocol loop to prevent hanging thread curr_ba = SimplePKIBA(1) import config config.node_id = 4 self.assertEqual(curr_ba.get_proposals_with_threshold(0), []) self.assertEqual(curr_ba.get_proposals_with_threshold(1000), []) self.assertEqual(curr_ba.get_proposals_with_threshold(-1), []) # single proposal, some votes curr_ba.votes = {"hi": set([1,2])} self.assertEqual(curr_ba.get_proposals_with_threshold(0), ['hi']) self.assertEqual(curr_ba.get_proposals_with_threshold(1), ['hi']) self.assertEqual(curr_ba.get_proposals_with_threshold(2), ['hi']) self.assertEqual(curr_ba.get_proposals_with_threshold(3), []) self.assertEqual(curr_ba.get_proposals_with_threshold(-1), ['hi']) self.assertEqual(curr_ba.get_proposals_with_threshold(100), []) # single proposal, no votes curr_ba.votes = {"hi": set([])} self.assertEqual(curr_ba.get_proposals_with_threshold(100), []) self.assertEqual(curr_ba.get_proposals_with_threshold(0), []) # multi proposal, mixed votes curr_ba.votes = {"hi": set([1,2,3,4]), "a": set([1,2]), "64": set([6])} self.assertEqual(set(curr_ba.get_proposals_with_threshold(0)), set(["hi", "a"])) self.assertEqual(set(curr_ba.get_proposals_with_threshold(1)), set(["hi", "a"])) self.assertEqual(curr_ba.get_proposals_with_threshold(3), ["hi"]) self.assertEqual(curr_ba.get_proposals_with_threshold(10), [])