def create_positive_gossip_transaction(block_hash, node_private): tx = PositiveGossipTransaction() tx.timestamp = Time.get_current_time() tx.block_hash = block_hash tx.pubkey = Private.publickey(node_private) tx.signature = Private.sign(tx.get_hash(), node_private) return tx
def create_negative_gossip_transaction(number_of_block, node_private): tx = NegativeGossipTransaction() tx.timestamp = Time.get_current_time() tx.number_of_block = number_of_block tx.pubkey = Private.publickey(node_private) tx.signature = Private.sign(tx.get_hash(), node_private) return tx
def test_parse_pack_gossip_negative(self): private = Private.generate() original = NegativeGossipTransaction() original.pubkey = Private.publickey(private) original.timestamp = Time.get_current_time() original.number_of_block = 47 original.signature = Private.sign(original.get_hash(), private) raw = original.pack() restored = NegativeGossipTransaction() restored.parse(raw) self.assertEqual(original.get_hash(), restored.get_hash())
def test_pack_parse_penalty_gossip_transaction(self): private = Private.generate() original = PenaltyGossipTransaction() original.timestamp = Time.get_current_time() block = BlockFactory.create_block_with_timestamp( [], timestamp=original.timestamp) gossip_positive_tx = PositiveGossipTransaction() gossip_positive_tx.pubkey = Private.publickey(private) gossip_positive_tx.timestamp = Time.get_current_time() gossip_positive_tx.block_hash = BlockFactory.sign_block( block, private).get_hash() gossip_positive_tx.signature = Private.sign(original.get_hash(), private) gossip_negative_tx = NegativeGossipTransaction() gossip_negative_tx.pubkey = Private.publickey(private) gossip_negative_tx.timestamp = Time.get_current_time() gossip_negative_tx.number_of_block = 47 gossip_negative_tx.signature = Private.sign(original.get_hash(), private) original.conflicts = [ gossip_positive_tx.get_hash(), gossip_negative_tx.get_hash() ] original.signature = Private.sign(original.get_hash(), private) original.block_hash = BlockFactory.sign_block(block, private).get_hash() raw = original.pack() restored = PenaltyGossipTransaction() restored.parse(raw) self.assertEqual(original.get_hash(), restored.get_hash())
def test_parse_pack_gossip_positive(self): private = Private.generate() original = PositiveGossipTransaction() original.pubkey = Private.publickey(private) original.timestamp = Time.get_current_time() block = BlockFactory.create_block_with_timestamp( [], timestamp=original.timestamp) original.block_hash = BlockFactory.sign_block(block, private).get_hash() original.signature = Private.sign(original.get_hash(), private) raw = original.pack() restored = PositiveGossipTransaction() restored.parse(raw) self.assertEqual(original.get_hash(), restored.get_hash())
def test_remove_from_validators_by_penalty_gossip(self): # base initialization dag = Dag(0) epoch = Epoch(dag) permissions = Permissions(epoch) node_private = Private.generate() initial_validators = Validators.read_genesis_validators_from_file() genesis_hash = dag.genesis_block().get_hash() prev_hash = genesis_hash for i in range(1, 9): block = BlockFactory.create_block_with_timestamp([prev_hash], BLOCK_TIME * i) signed_block = BlockFactory.sign_block(block, node_private) dag.add_signed_block(i, signed_block) prev_hash = block.get_hash() # get one of validators genesis_validator_private = Private.generate() genesis_validator_public = initial_validators[9].public_key # put to 10 block gossip+ AND gossip- by one node block = BlockFactory.create_block_with_timestamp([prev_hash], BLOCK_TIME * 10) gossip_negative_tx = NegativeGossipTransaction() gossip_negative_tx.pubkey = genesis_validator_public gossip_negative_tx.timestamp = Time.get_current_time() gossip_negative_tx.number_of_block = 5 gossip_negative_tx.signature = Private.sign( gossip_negative_tx.get_hash(), genesis_validator_private) # create and add to block negative gossip block.system_txs.append(gossip_negative_tx) gossip_positive_tx = PositiveGossipTransaction() gossip_positive_tx.pubkey = genesis_validator_public gossip_positive_tx.timestamp = Time.get_current_time() gossip_positive_tx.block_hash = dag.blocks_by_number[5][0].get_hash() gossip_positive_tx.signature = Private.sign( gossip_positive_tx.get_hash(), genesis_validator_private) # create and add to block positive gossip for same number 5 block block.system_txs.append(gossip_positive_tx) signed_block = BlockFactory.sign_block(block, genesis_validator_private) dag.add_signed_block(10, signed_block) prev_hash = block.get_hash() # -------------------------------------------------- # put to 11 block penalty gossip block = BlockFactory.create_block_with_timestamp([prev_hash], BLOCK_TIME * 11) penalty_gossip_tx = PenaltyGossipTransaction() penalty_gossip_tx.timestamp = Time.get_current_time() penalty_gossip_tx.conflicts = [ gossip_positive_tx.get_hash(), gossip_negative_tx.get_hash() ] # set genesis validator for sign penalty gossip penalty_gossip_tx.signature = Private.sign( penalty_gossip_tx.get_hash(), genesis_validator_private) block.system_txs.append(penalty_gossip_tx) signed_block = BlockFactory.sign_block(block, genesis_validator_private) dag.add_signed_block(11, signed_block) prev_hash = block.get_hash() # -------------------------------------------------- # verify that genesis node is steel in validators list current_epoch_hash = epoch.get_epoch_hashes() # for now we DO NOT NEED to recalculate validators (send genesis block hash) resulting_validators = permissions.get_validators( current_epoch_hash.get(prev_hash)) pub_keys = [] for validator in resulting_validators: pub_keys.append(validator.public_key) self.assertIn(genesis_validator_public, pub_keys) # produce epoch till end from chain.params import ROUND_DURATION for i in range(12, (ROUND_DURATION * 6 + 4)): block = BlockFactory.create_block_with_timestamp([prev_hash], BLOCK_TIME * i) signed_block = BlockFactory.sign_block(block, node_private) dag.add_signed_block(i, signed_block) prev_hash = block.get_hash() # check for new epoch self.assertTrue(epoch.is_new_epoch_upcoming(i)) self.assertTrue(epoch.current_epoch == 2) # recalculate validators for last block hash resulting_validators = permissions.get_validators(prev_hash) pub_keys = [] for validator in resulting_validators: pub_keys.append(validator.public_key) self.assertNotIn(genesis_validator_public, pub_keys)
def create_block_dummy(prev_hashes): block = Block() block.prev_hashes = prev_hashes block.timestamp = Time.get_current_time() block.system_txs = [] return block
def get_current_timeframe_block_number(self): return self.get_block_number_from_timestamp(Time.get_current_time())
def create_penalty_gossip_transaction(conflict, node_private): tx = PenaltyGossipTransaction() tx.timestamp = Time.get_current_time() tx.conflicts = conflict tx.signature = Private.sign(tx.get_hash(), node_private) return tx
def __init__(self): self.node_to_visualize_after_exit = 0 self.params_validate() self.discrete_mode = True self.malicious_validators_count = GENESIS_VALIDATORS_COUNT / 2 - 1 # set up logging to file - see previous section for more details self.logger = logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-6s %(name)-6s %(message)s') if self.discrete_mode: Time.use_test_time() Time.set_current_time(BLOCK_TIME) else: Time.set_current_time(int(datetime.datetime.now().timestamp())) self.genesis_creation_time = Time.get_current_time() - BLOCK_TIME # so we start right from the first block self.private_keys = BlockSigners() self.network = Network() self.nodes = [] self.tasks = [] try: # ------------------------------------- # main init section # ------------------------------------- self.launch() # add some extra nodes #self.add_node(10) # ------------------------------------- if self.discrete_mode: should_continue = True terminated_nodes_count = 0 while should_continue: initial_node_count = len(self.nodes) - 1 # one node less because of announcer for node in self.nodes: try: if not node.terminated: node.step() except AssertionError: print("Node", node.node_id, "crashed") self.network.unregister_node(node) node.terminated = True terminated_nodes_count += 1 if terminated_nodes_count == initial_node_count: print("No alive nodes left. Terminating") should_continue = False break Time.advance_time(1) # add some nodes on defined time # will be possible after syncronization mechanism will be implemented) # if Time.get_current_time() == 40: # self.add_node(1) else: self.tasks = [node.run() for node in self.nodes] loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.gather(*self.tasks)) loop.close() finally: if self.node_to_visualize_after_exit: save_dag_to_graphviz(self.node_to_visualize_after_exit.dag) show_node_stats(self.node_to_visualize_after_exit)