def test_waiting_confirmation_timeout(self): block_hash_1 = Sha256Hash(helpers.generate_hash()) block_msg_1 = create_block_message(block_hash_1) block_hash_2 = Sha256Hash(helpers.generate_hash()) block_msg_2 = create_block_message(block_hash_2, block_hash_1) # first block gets sent immediately self.block_queuing_service.push(block_hash_1, block_msg_1) self.block_queuing_service.push(block_hash_2, block_msg_2) self.assertEqual(1, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0]) self.assertEqual(1, len(self.block_queuing_service)) self.assertIn(block_hash_1, self.block_queuing_service) self.assertIn(block_hash_2, self.block_queuing_service) time.time = MagicMock(return_value=time.time() + gateway_constants.MAX_INTERVAL_BETWEEN_BLOCKS_S) self.node.alarm_queue.fire_alarms() self.assertEqual(2, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_2, self.node.broadcast_to_nodes_messages[1]) self.assertEqual(0, len(self.block_queuing_service)) self.assertIn(block_hash_1, self.block_queuing_service) self.assertIn(block_hash_2, self.block_queuing_service)
def test_waiting_confirmation_timeout(self): block_hash_1 = Sha256Hash(helpers.generate_hash()) block_msg_1 = helpers.create_block_message(block_hash_1) block_hash_2 = Sha256Hash(helpers.generate_hash()) block_msg_2 = helpers.create_block_message(block_hash_2, block_hash_1) # first block gets sent immediately self.node.block_queuing_service_manager.push(block_hash_1, block_msg_1) self.node.block_queuing_service_manager.push(block_hash_2, block_msg_2) self._assert_length_of_enqueued_messages(1) self._assert_block_in_enqueued_messages_index(block_msg_1, 0) self._assert_len_of_block_queuing_services(1) self._assert_block_in_queuing_services(block_hash_1) self._assert_block_in_queuing_services(block_hash_2) time.time = MagicMock( return_value=time.time() + gateway_constants.MAX_INTERVAL_BETWEEN_BLOCKS_S ) self.node.alarm_queue.fire_alarms() self._assert_length_of_enqueued_messages(2) self._assert_block_in_enqueued_messages_index(block_msg_2, 1) self._assert_len_of_block_queuing_services(0) self._assert_block_in_queuing_services(block_hash_1) self._assert_block_in_queuing_services(block_hash_2)
def test_block_added_waiting_for_previous_block_confirmation(self): block_hash_1 = Sha256Hash(helpers.generate_hash()) block_msg_1 = create_block_message(block_hash_1) block_hash_2 = Sha256Hash(helpers.generate_hash()) block_msg_2 = create_block_message(block_hash_2, block_hash_1) # first block gets sent immediately self.block_queuing_service.push(block_hash_1, block_msg_1) self.assertEqual(1, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0]) self.assertEqual(0, len(self.block_queuing_service)) self.assertIn(block_hash_1, self.block_queuing_service) # no confirmation, wait on block 1 self.block_queuing_service.push(block_hash_2, block_msg_2) self.assertEqual(1, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0]) self.assertEqual(1, len(self.block_queuing_service)) self.assertIn(block_hash_1, self.block_queuing_service) self.assertIn(block_hash_2, self.block_queuing_service) self.block_queuing_service.mark_blocks_seen_by_blockchain_node( [block_hash_1]) self.assertEqual(2, len(self.node.broadcast_to_nodes_messages)) self.assertEqual(block_msg_2, self.node.broadcast_to_nodes_messages[1]) self.assertEqual(0, len(self.block_queuing_service))
def test_msg_key_wait_for_broadcast(self): ont_block = self.ont_block() bx_block = self.bx_block(ont_block) key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) self.gateway_node.broadcast.assert_not_called() key_message = KeyMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", key) self.sut.msg_key(key_message) # handle duplicate broadcasts self.sut.msg_key(key_message) self.sut.msg_key(key_message) self.assertEqual(1, len(self.gateway_node.in_progress_blocks)) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) self._assert_block_sent(ont_block)
def test_broadcast_to_connection_type(self): relay_all_conn = self._add_connection(0, 9000, ALL_NETWORK_NUM, ConnectionType.RELAY_ALL) relay_block_conn = self._add_connection(1, 9001, ALL_NETWORK_NUM, ConnectionType.RELAY_BLOCK) relay_transaction_conn = self._add_connection(2, 9002, ALL_NETWORK_NUM, ConnectionType.RELAY_TRANSACTION) gateway_conn = self._add_connection(3, 9003, ALL_NETWORK_NUM, ConnectionType.EXTERNAL_GATEWAY) block_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250)) self.sut.broadcast(block_message, BroadcastOptions(connection_types=[ConnectionType.RELAY_BLOCK])) tx_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250)) self.sut.broadcast(tx_message, BroadcastOptions(connection_types=[ConnectionType.RELAY_TRANSACTION])) gateway_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250)) self.sut.broadcast(gateway_message, BroadcastOptions(connection_types=[ConnectionType.GATEWAY])) self.assertIn(block_message, relay_all_conn.enqueued_messages) self.assertIn(block_message, relay_block_conn.enqueued_messages) self.assertNotIn(block_message, relay_transaction_conn.enqueued_messages) self.assertNotIn(block_message, gateway_conn.enqueued_messages) self.assertIn(tx_message, relay_all_conn.enqueued_messages) self.assertNotIn(tx_message, relay_block_conn.enqueued_messages) self.assertIn(tx_message, relay_transaction_conn.enqueued_messages) self.assertNotIn(tx_message, gateway_conn.enqueued_messages) self.assertNotIn(gateway_message, relay_all_conn.enqueued_messages) self.assertNotIn(gateway_message, relay_block_conn.enqueued_messages) self.assertNotIn(gateway_message, relay_transaction_conn.enqueued_messages) self.assertIn(gateway_message, gateway_conn.enqueued_messages)
def test_waiting_recovery_last_block_is_removed(self): block_hash1 = Sha256Hash(helpers.generate_hash()) block_msg1 = helpers.create_block_message(block_hash1) block_hash2 = Sha256Hash(helpers.generate_hash()) block_msg2 = helpers.create_block_message(block_hash2, block_hash1) block_hash3 = Sha256Hash(helpers.generate_hash()) block_msg3 = helpers.create_block_message(block_hash3, block_hash2) self.node.block_queuing_service_manager.push( block_hash1, block_msg1, waiting_for_recovery=False) self.node.block_queuing_service_manager.push( block_hash2, block_msg2, waiting_for_recovery=False) self.node.block_queuing_service_manager.push(block_hash3, block_msg3, waiting_for_recovery=True) self._assert_length_of_enqueued_messages(1) self._assert_len_of_block_queuing_services(2) self._assert_block_in_enqueued_messages_index(block_msg1, 0) self._reset_enqueue_msg_mocks() self.block_queuing_service.remove(block_hash3) self.block_queuing_service_2.remove(block_hash3) self._assert_length_of_enqueued_messages(0) self._assert_len_of_block_queuing_services(1) self._mark_blocks_seen_by_blockchain_nodes([block_hash1]) self._assert_length_of_enqueued_messages(1) self._assert_len_of_block_queuing_services(0) self._assert_block_in_enqueued_messages_index(block_msg2, 0)
def test_msg_broadcast_wait_for_key(self): ont_block = self.ont_block() bx_block = self.bx_block(ont_block) key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) # handle duplicate messages self.sut.msg_broadcast(broadcast_message) self.sut.msg_broadcast(broadcast_message) self.assertEqual(3, len(self.gateway_node.broadcast.call_args_list)) for call, conn_type in self.gateway_node.broadcast.call_args_list: msg, conn = call self.assertTrue(isinstance(msg, BlockReceivedMessage)) self.gateway_node.broadcast.reset_mock() self.assertEqual(1, len(self.gateway_node.in_progress_blocks)) key_message = KeyMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", key) self.sut.msg_key(key_message) self._assert_block_sent(ont_block)
def test_get_object_size(self): mock_node = MockNode(get_common_opts(1234)) object_size = memory_utils.get_object_size(mock_node) self.assertIsInstance(object_size, ObjectSize) self.assertTrue(object_size.size > 0) self.assertTrue(object_size.flat_size > 0) self.assertTrue(object_size.is_actual_size) self.assertEqual(0, len(object_size.references)) ex_set = ExpiringSet(AlarmQueue(), 10, "testset") s = set() h1 = Sha256Hash(b"1" * 32) h2 = Sha256Hash(b"0" * 32) print(memory_utils.get_object_size(ex_set).size) print(memory_utils.get_object_size(s).size) print(memory_utils.get_object_size(h1).size) print(memory_utils.get_object_size(h2).size) print(memory_utils.get_special_size(ex_set).size) print(memory_utils.get_special_size(s).size) print(memory_utils.get_special_size(h1).size) print(memory_utils.get_special_size(h2).size) ex_set.add(h1) ex_set.add(h2) s.add(h1) s.add(h2) print(memory_utils.get_object_size(ex_set).size) print(memory_utils.get_special_size(ex_set).size) print(memory_utils.get_object_size(s).size)
def test_berlin_block_from_bytes(self): block: Block = rlp.decode(eth_fixtures.BERLIN_BLOCK, Block) self.assertEqual( Sha256Hash.from_string( "0ad3836807aa90218884be62c8dd912fe5228aafa6fc2a7c21028e8c09bc91ef" ), block.header.hash_object(), ) self.assertEqual(2, len(block.transactions)) legacy_tx = block.transactions[0] self.assertIsInstance(legacy_tx, LegacyTransaction) self.assertEqual( Sha256Hash.from_string( "77b19baa4de67e45a7b26e4a220bccdbb6731885aa9927064e239ca232023215" ), legacy_tx.hash(), ) acl_tx = block.transactions[1] self.assertIsInstance(acl_tx, AccessListTransaction) self.assertEqual( Sha256Hash.from_string( "554af720acf477830f996f1bc5d11e54c38aa40042aeac6f66cb66f9084a959d" ), acl_tx.hash(), ) re_encoded = rlp.encode(block) self.assertEqual(block, rlp.decode(re_encoded, Block))
def _test_mark_blocks_and_request_cleanup(self): marked_block = Sha256Hash( binary=helpers.generate_bytearray(SHA256_HASH_LEN)) prev_block = Sha256Hash( binary=helpers.generate_bytearray(SHA256_HASH_LEN)) tracked_blocks = [] self.cleanup_service.on_new_block_received(marked_block, prev_block) self.transaction_service.track_seen_short_ids(marked_block, []) for _ in range(self.block_confirmations_count - 1): tracked_block = Sha256Hash( binary=helpers.generate_bytearray(SHA256_HASH_LEN)) self.transaction_service.track_seen_short_ids(tracked_block, []) tracked_blocks.append(tracked_block) unmarked_block = Sha256Hash( binary=helpers.generate_bytearray(SHA256_HASH_LEN)) self.assertIsNone(self.cleanup_service.last_confirmed_block) self.cleanup_service.mark_blocks_and_request_cleanup( [marked_block, *tracked_blocks]) self.assertEqual(marked_block, self.cleanup_service.last_confirmed_block) self.assertTrue( self.cleanup_service.is_marked_for_cleanup(marked_block)) self.assertFalse( self.cleanup_service.is_marked_for_cleanup(unmarked_block)) self.assertEqual(marked_block, self.cleanup_service.last_confirmed_block)
def test_txs_with_short_ids_message(self): txs_info = [ TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)), helpers.generate_bytearray(200), 111), TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)), helpers.generate_bytearray(300), 222), TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)), helpers.generate_bytearray(400), 333) ] msg = TxsMessage(txs=txs_info) msg_bytes = msg.rawbytes() self.assertTrue(msg_bytes) parsed_msg = TxsMessage(buf=msg_bytes) self.assertTrue(parsed_msg) parsed_txs_info = parsed_msg.get_txs() self.assertEqual(len(parsed_txs_info), len(txs_info)) for index in range(len(txs_info)): self.assertEqual(parsed_txs_info[index].short_id, txs_info[index].short_id) self.assertEqual(parsed_txs_info[index].contents, txs_info[index].contents) self.assertEqual(parsed_txs_info[index].hash, txs_info[index].hash)
def test_get_txs_block_recovery_encrypted(self): block: BlockOntMessage = self.ont_block() transactions: List[TxOntMessage] = self.ont_transactions(block) # assign short ids that the local connection won't know about until it gets the txs message remote_transaction_service = ExtensionTransactionService( MockNode(gateway_helpers.get_gateway_opts(8999)), 0) short_id_mapping = {} for i, transaction in enumerate(transactions): tx_hash = transaction.tx_hash() remote_transaction_service.assign_short_id(tx_hash, i + 1) remote_transaction_service.set_transaction_contents( tx_hash, transaction.rawbytes()) short_id_mapping[tx_hash] = TransactionInfo( tx_hash, transaction.rawbytes(), i + 1) bx_block = bytes( self.gateway_node.message_converter.block_to_bx_block( block, remote_transaction_service)[0]) self.gateway_node.block_recovery_service.add_block = \ MagicMock(wraps=self.gateway_node.block_recovery_service.add_block) self.gateway_node.send_msg_to_node = MagicMock() self.gateway_node.broadcast = MagicMock() key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) key_message = KeyMessage(Sha256Hash(block_hash), DEFAULT_NETWORK_NUM, "", key) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), DEFAULT_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) self.gateway_node.broadcast.reset_mock() self.sut.msg_key(key_message) self.gateway_node.block_recovery_service.add_block.assert_called_once() self.assertEqual(2, self.gateway_node.broadcast.call_count) recovery_broadcast = self.gateway_node.broadcast.call_args_list[0] ((gettxs_message, ), recovery_kwargs) = recovery_broadcast self.assertIsInstance(gettxs_message, GetTxsMessage) self.assertIn(ConnectionType.RELAY_TRANSACTION, recovery_kwargs["connection_types"]) key_broadcast = self.gateway_node.broadcast.call_args_list[1] ((key_message, _conn), recovery_kwargs) = key_broadcast self.assertIsInstance(key_message, KeyMessage) self.assertIn(ConnectionType.GATEWAY, recovery_kwargs["connection_types"]) txs = [tx for tx in short_id_mapping.values()] txs_message = TxsMessage(txs=txs) self.sut.msg_txs(txs_message) self._assert_block_sent(block)
def test_block_added_waiting_for_previous_block_confirmation(self): block_hash_1 = Sha256Hash(helpers.generate_hash()) block_msg_1 = helpers.create_block_message(block_hash_1) block_hash_2 = Sha256Hash(helpers.generate_hash()) block_msg_2 = helpers.create_block_message(block_hash_2, block_hash_1) # first block gets sent immediately self.node.block_queuing_service_manager.push(block_hash_1, block_msg_1) self._assert_length_of_enqueued_messages(1) self._assert_block_in_enqueued_messages_index(block_msg_1, 0) self._assert_len_of_block_queuing_services(0) self._assert_block_in_queuing_services(block_hash_1) # no confirmation, wait on block 1 self.node.block_queuing_service_manager.push(block_hash_2, block_msg_2) self._assert_length_of_enqueued_messages(1) self._assert_block_in_enqueued_messages_index(block_msg_1, 0) self._assert_len_of_block_queuing_services(1) self._assert_block_in_queuing_services(block_hash_1) self._assert_block_in_queuing_services(block_hash_2) self._mark_blocks_seen_by_blockchain_nodes( [block_hash_1] ) self._assert_length_of_enqueued_messages(2) self._assert_block_in_enqueued_messages_index(block_msg_2, 1) self._assert_len_of_block_queuing_services(0)
def test_block_removed_with_ttl_check(self): self.node.has_active_blockchain_peer = MagicMock(return_value=False) block_hash_start = Sha256Hash(helpers.generate_hash()) block_msg_start = helpers.create_block_message(block_hash_start) block_hash_end = Sha256Hash(helpers.generate_hash()) block_msg_end = helpers.create_block_message(block_hash_end) self.node.block_queuing_service_manager.push(block_hash_start, block_msg_start) for i in range(2, BLOCK_QUEUE_LENGTH_LIMIT + 1): block_hash = Sha256Hash(helpers.generate_hash()) block_msg = helpers.create_block_message(block_hash) self.node.block_queuing_service_manager.push(block_hash, block_msg) self.assertEqual(BLOCK_QUEUE_LENGTH_LIMIT, len(self.block_queuing_service)) self._assert_length_of_enqueued_messages(0) self.node.has_active_blockchain_peer = MagicMock(return_value=True) time.time = MagicMock( return_value=time.time() + MAX_BLOCK_CACHE_TIME_S * 2 ) self.assertEqual(BLOCK_QUEUE_LENGTH_LIMIT, len(self.block_queuing_service._block_queue)) self.node.block_queuing_service_manager.push(block_hash_end, block_msg_end) self._mark_blocks_seen_by_blockchain_nodes([block_hash_end]) self.assertEqual(0, len(self.block_queuing_service._block_queue))
def _tx_cache_key_to_hash(self, transaction_cache_key) -> Sha256Hash: if isinstance(transaction_cache_key, Sha256Hash): return transaction_cache_key if isinstance(transaction_cache_key, (bytes, bytearray, memoryview)): return Sha256Hash(transaction_cache_key) return Sha256Hash(bytearray(transaction_cache_key.binary()))
def create_block_message( block_hash: Optional[Sha256Hash] = None, previous_block_hash: Optional[Sha256Hash] = None, ) -> AbstractBlockMessage: if block_hash is None: block_hash = Sha256Hash(generate_hash()) if previous_block_hash is None: previous_block_hash = Sha256Hash(generate_hash()) return TestBlockMessage(previous_block_hash, block_hash)
def _tx_cache_key_to_hash(self, transaction_cache_key: Union[Sha256Hash, bytes, bytearray, memoryview, str]) \ -> Sha256Hash: if isinstance(transaction_cache_key, Sha256Hash): return transaction_cache_key if isinstance(transaction_cache_key, (bytes, bytearray, memoryview)): return Sha256Hash(transaction_cache_key) return Sha256Hash(convert.hex_to_bytes(transaction_cache_key))
def test_msg_broadcast_duplicate_block_with_different_short_id(self): # test scenario when first received block is compressed with unknown short ids, # but second received block is compressed with known short ids ont_block = self.ont_block() block_hash = ont_block.block_hash() transactions = self.bx_transactions() unknown_sid_transaction_service = ExtensionTransactionService(MockNode( gateway_helpers.get_gateway_opts(8999)), 0) for i, transaction in enumerate(transactions): unknown_sid_transaction_service.assign_short_id(transaction.tx_hash(), i) unknown_sid_transaction_service.set_transaction_contents(transaction.tx_hash(), transaction.tx_val()) unknown_short_id_block = bytes( self.gateway_node.message_converter.block_to_bx_block( ont_block, unknown_sid_transaction_service, True, self.gateway_node.network.min_tx_age_seconds )[0] ) unknown_key, unknown_cipher = symmetric_encrypt(unknown_short_id_block) unknown_block_hash = crypto.double_sha256(unknown_cipher) unknown_message = BroadcastMessage(Sha256Hash(unknown_block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, bytearray(unknown_short_id_block)) unknown_key_message = KeyMessage(Sha256Hash(unknown_block_hash), self.TEST_NETWORK_NUM, "", unknown_key) local_transaction_service = self.gateway_node.get_tx_service() for i, transaction in enumerate(transactions): local_transaction_service.assign_short_id(transaction.tx_hash(), i + 20) local_transaction_service.set_transaction_contents(transaction.tx_hash(), transaction.tx_val()) known_short_id_block = bytes( self.gateway_node.message_converter.block_to_bx_block( ont_block, local_transaction_service, True, self.gateway_node.network.min_tx_age_seconds )[0] ) known_key, known_cipher = symmetric_encrypt(known_short_id_block) known_block_hash = crypto.double_sha256(known_cipher) known_message = BroadcastMessage(Sha256Hash(known_block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, bytearray(known_short_id_block)) known_key_message = KeyMessage(Sha256Hash(known_block_hash), self.TEST_NETWORK_NUM, "", known_key) self.sut.msg_broadcast(unknown_message) self.sut.msg_key(unknown_key_message) self.assertEqual(1, len(self.gateway_node.block_queuing_service)) self.assertEqual(True, self.gateway_node.block_queuing_service._blocks_waiting_for_recovery[block_hash]) self.assertEqual(1, len(self.gateway_node.block_recovery_service._block_hash_to_bx_block_hashes)) self.assertNotIn(block_hash, self.gateway_node.blocks_seen.contents) self.sut.msg_broadcast(known_message) self.sut.msg_key(known_key_message) self.gateway_node_sut.msg_get_data(GetDataOntMessage(self.magic, InventoryOntType.MSG_BLOCK.value, block_hash)) self.gateway_node.broadcast.assert_called() self.assertEqual(0, len(self.gateway_node.block_queuing_service)) self.assertEqual(0, len(self.gateway_node.block_recovery_service._block_hash_to_bx_block_hashes)) self.assertIn(block_hash, self.gateway_node.blocks_seen.contents)
def _wrap_sha256( self, transaction_hash: Union[bytes, bytearray, memoryview, Sha256Hash] ) -> Sha256Hash: if isinstance(transaction_hash, Sha256Hash): return transaction_hash if isinstance(transaction_hash, (bytes, bytearray, memoryview)): return Sha256Hash(binary=transaction_hash) return Sha256Hash(binary=convert.hex_to_bytes(transaction_hash))
def test_init(self): with self.assertRaises(ValueError): Sha256Hash(bytearray([i for i in range(SHA256_HASH_LEN - 1)])) with self.assertRaises(ValueError): Sha256Hash(bytearray()) expected = self.int_hash_31a.binary actual = self.to_31 self.assertEqual(expected, actual) actual = Sha256Hash(memoryview(actual)) self.assertEqual(expected, actual.binary) self.assertIsNotNone(hash(self.int_hash_all_0))
def test_place_hold(self): hash1 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)) hash2 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)) self.sut.place_hold(hash1, self.dummy_connection) self.sut.place_hold(hash2, self.dummy_connection) self.assertEqual(2, len(self.sut._holds.contents)) self.assertEqual(2, len(self.node.broadcast_messages)) self.assertEqual(BlockHoldingMessage(hash1, network_num=1), self.node.broadcast_messages[0][0]) self.assertEqual(BlockHoldingMessage(hash2, network_num=1), self.node.broadcast_messages[1][0])
def _test_track_short_ids_seen_in_block(self): short_ids = [1, 2, 3, 4, 5] transaction_hashes = list(map(crypto.double_sha256, map(bytes, short_ids))) transaction_contents = list(map(crypto.double_sha256, transaction_hashes)) for i, short_id in enumerate(short_ids): transaction_key = self.transaction_service.get_transaction_key(transaction_hashes[i]) self.transaction_service._tx_cache_key_to_contents[transaction_key.transaction_cache_key] = \ transaction_contents[i] self.transaction_service.assign_short_id_by_key(transaction_key, short_id) self.transaction_service.set_final_tx_confirmations_count(7) # 1st block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [1]) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 2nd block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [2]) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 3rd block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [3, 4]) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 4th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 5th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 6th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([1, 2, 3, 4, 5], []) # 7th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([2, 3, 4], [0, 1]) # 8th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([3, 4], [0, 1, 2]) # 9th block with short ids arrives block_hash = bytearray(helpers.generate_bytearray(32)) self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), []) self._verify_txs_in_tx_service([], [0, 1, 2, 3, 4])
def test_place_hold_duplicates(self): hash1 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)) hash2 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)) self.sut.place_hold(hash1, self.dummy_connection) time.time = MagicMock(return_value=time.time() + 5) self.sut.place_hold(hash1, self.dummy_connection) self.sut.place_hold(hash1, self.dummy_connection) self.sut.place_hold(hash2, self.dummy_connection) self.assertEqual(2, len(self.sut._holds.contents)) hold1 = self.sut._holds.contents[hash1] hold2 = self.sut._holds.contents[hash2] self.assertTrue(hold2.hold_message_time - hold1.hold_message_time >= 5)
def test_last_block_is_recovered(self): block_hash1 = Sha256Hash(helpers.generate_hash()) block_msg1 = helpers.create_block_message() block_hash2 = Sha256Hash(helpers.generate_hash()) block_msg2 = helpers.create_block_message(block_hash2, block_hash1) block_hash3 = Sha256Hash(helpers.generate_hash()) block_msg3 = helpers.create_block_message(block_hash3, block_hash2) self.node.block_queuing_service_manager.push( block_hash1, block_msg1, waiting_for_recovery=False ) self._mark_block_seen_by_blockchain_nodes( block_hash1, None ) self.node.block_queuing_service_manager.push( block_hash2, block_msg2, waiting_for_recovery=False ) self._mark_block_seen_by_blockchain_nodes( block_hash2, None ) self.node.block_queuing_service_manager.push( block_hash3, block_msg3, waiting_for_recovery=True ) self._assert_length_of_enqueued_messages(2) self._assert_len_of_block_queuing_services(1) self._assert_block_in_enqueued_messages_index(block_msg1, 0) self._assert_block_in_enqueued_messages_index(block_msg2, 1) self._reset_enqueue_msg_mocks() self._reset_enqueue_msg_mocks() # don't send, since not recovered enough though timeout time.time = MagicMock( return_value=time.time() + MAX_INTERVAL_BETWEEN_BLOCKS_S ) self.node.alarm_queue.fire_alarms() self._assert_length_of_enqueued_messages(0) self._assert_len_of_block_queuing_services(1) self.node.block_queuing_service_manager.update_recovered_block( block_hash3, block_msg3 ) self._assert_length_of_enqueued_messages(1) self._assert_len_of_block_queuing_services(0) self._assert_block_in_enqueued_messages_index(block_msg3, 0)
def _parse(self): txs = [] off = constants.BX_HDR_COMMON_OFF txs_count, = struct.unpack_from('<L', self.buf, off) off += constants.UL_INT_SIZE_IN_BYTES logger.debug("Block recovery: received {0} txs in the message.".format(txs_count)) for tx_index in range(txs_count): tx_sid, = struct.unpack_from('<L', self.buf, off) off += constants.UL_INT_SIZE_IN_BYTES tx_hash = Sha256Hash(self._memoryview[off:off + bxcommon.utils.crypto.SHA256_HASH_LEN]) off += bxcommon.utils.crypto.SHA256_HASH_LEN tx_size, = struct.unpack_from('<L', self.buf, off) off += constants.UL_INT_SIZE_IN_BYTES tx = self._memoryview[off:off + tx_size] off += tx_size txs.append(TransactionInfo(tx_hash, tx, tx_sid)) self._txs = txs
def test_update_recovered_block(self): block_queuing_service = self.node.build_block_queuing_service( self.node_conn) self.node.block_queuing_service_manager.add_block_queuing_service( self.node_conn, block_queuing_service) block_queuing_service.update_recovered_block = MagicMock() block_queuing_service_2 = self.node.build_block_queuing_service( self.node_conn_2) self.node.block_queuing_service_manager.add_block_queuing_service( self.node_conn_2, block_queuing_service_2) block_queuing_service_2.update_recovered_block = MagicMock() block_queuing_service_3 = self.node.build_block_queuing_service( self.node_conn_3) self.node.block_queuing_service_manager.add_block_queuing_service( self.node_conn_3, block_queuing_service_3) block_queuing_service_3.update_recovered_block = MagicMock() self.assertEqual( len(self.node.block_queuing_service_manager. blockchain_peer_to_block_queuing_service), 3) block_hash = Sha256Hash(helpers.generate_hash()) block_msg = helpers.create_block_message(block_hash) self.node.block_queuing_service_manager.update_recovered_block( block_hash, block_msg) block_queuing_service.update_recovered_block.assert_called_with( block_hash, block_msg) block_queuing_service_2.update_recovered_block.assert_called_with( block_hash, block_msg) block_queuing_service_3.update_recovered_block.assert_called_with( block_hash, block_msg) self.assertIn(block_hash, self.node.block_storage) self.assertEqual(block_msg, self.node.block_storage[block_hash])
def test_remove_block(self): block_queuing_service = self.node.build_block_queuing_service( self.node_conn) self.node.block_queuing_service_manager.add_block_queuing_service( self.node_conn, block_queuing_service) block_queuing_service.remove = MagicMock() block_queuing_service_2 = self.node.build_block_queuing_service( self.node_conn_2) self.node.block_queuing_service_manager.add_block_queuing_service( self.node_conn_2, block_queuing_service_2) block_queuing_service_2.remove = MagicMock() block_hash = Sha256Hash(helpers.generate_hash()) block_msg = helpers.create_block_message(block_hash) self.node.block_queuing_service_manager.store_block_data( block_hash, block_msg) block_queuing_service._blocks.add(block_hash) block_queuing_service_2._blocks.add(block_hash) self.assertIn(block_hash, self.node.block_storage) self.assertEqual(block_msg, self.node.block_storage[block_hash]) self.node.block_queuing_service_manager.remove(block_hash) self.assertNotIn(block_hash, self.node.block_storage) block_queuing_service.remove.assert_called_with(block_hash) block_queuing_service_2.remove.assert_called_with(block_hash)
def add_block(self, bx_block: memoryview, block_hash: Sha256Hash, unknown_tx_sids: List[int], unknown_tx_hashes: List[Sha256Hash]): """ Adds a block that needs to recovery. Tracks unknown short ids and contents as they come in. :param bx_block: bytearray representation of compressed block :param block_hash: original ObjectHash of block :param unknown_tx_sids: list of unknown short ids :param unknown_tx_hashes: list of unknown tx ObjectHashes """ logger.trace( "Recovering block with {} unknown short ids and {} contents: {}", len(unknown_tx_sids), len(unknown_tx_hashes), block_hash) bx_block_hash = Sha256Hash(crypto.double_sha256(bx_block)) self._bx_block_hash_to_block[bx_block_hash] = bx_block self._bx_block_hash_to_block_hash[bx_block_hash] = block_hash self._bx_block_hash_to_sids[bx_block_hash] = set(unknown_tx_sids) self._bx_block_hash_to_tx_hashes[bx_block_hash] = set( unknown_tx_hashes) self._block_hash_to_bx_block_hashes[block_hash].add(bx_block_hash) for sid in unknown_tx_sids: self._sid_to_bx_block_hashes[sid].add(bx_block_hash) for tx_hash in unknown_tx_hashes: self._tx_hash_to_bx_block_hashes[tx_hash].add(bx_block_hash) self._blocks_expiration_queue.add(bx_block_hash) self._schedule_cleanup()
async def test_blxr_tx_from_json(self): tx_json = { 'from': '0xc165599b5e418bb9d8a19090696ea2403b2927ed', 'gas': "0x5208", 'gasPrice': "0xc1b759d70", 'hash': '0xd569674ad9fcaaedcb6867b7896067b445d4a838316be4292c474df17bf4bd50', 'input': '0x', 'nonce': "0x14", 'to': '0xdb5f0c1f4198bc6ffa98b35f7188f82740b8caf7', 'value': "0x3e871b540c000", 'v': '0x26', 'r': '0x484bc950fb2d595500baa604774cb8d156a677198e087801936f38ca0b27049', 's': '0x7ca82ef7b6938c2e96966dd940b186c9cdc0c7f42b2843adbc0751bb6e67a2d4' } result = await self.request(BxJsonRpcRequest( "1", RpcRequestType.BLXR_TX, { rpc_constants.TRANSACTION_JSON_PARAMS_KEY: tx_json, "quota_type": "paid_daily_quota" } )) self.assertEqual("1", result.id) self.assertIsNone(result.error) self.assertEqual("ad6f9332384194f80d8e49af8f093ad019b3f6b7173eb2956a46c9a0d8c4d03c", result.result["tx_hash"]) self.assertEqual(ACCOUNT_ID, result.result["account_id"]) self.assertEqual("paid_daily_quota", result.result["quota_type"]) self.assertEqual(1, len(self.gateway_node.broadcast_messages)) self.assertEqual( Sha256Hash(convert.hex_to_bytes("ad6f9332384194f80d8e49af8f093ad019b3f6b7173eb2956a46c9a0d8c4d03c")), self.gateway_node.broadcast_messages[0][0].tx_hash() )
def test_propagate_block_to_network_unencrypted_block(self): self.node.opts.encrypt_blocks = False block_message = helpers.generate_bytearray(50) block_info = BlockInfo( Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)), [], datetime.datetime.utcnow(), datetime.datetime.utcnow(), 0, 1, helpers.generate_bytearray(crypto.SHA256_HASH_LEN), helpers.generate_bytearray(crypto.SHA256_HASH_LEN), 0, 0, 0, []) connection = MockConnection( MockSocketConnection(1, self.node, ip_address=LOCALHOST, port=9000), self.node) self.neutrality_service.propagate_block_to_network( block_message, connection, block_info) self.assertEqual(1, len(self.node.broadcast_messages)) broadcast_message, connection_types = self.node.broadcast_messages[0] # self.assertTrue(any(ConnectionType.RELAY_BLOCK & connection_type for connection_type in connection_types)) self.assertTrue( all(ConnectionType.RELAY_BLOCK in connection_type for connection_type in connection_types)) self.assertEqual(block_info.block_hash, broadcast_message.block_hash()) self.assertNotIn(block_info.block_hash, self.node.in_progress_blocks._cache) self.assertNotIn(broadcast_message.block_hash(), self.neutrality_service._receipt_tracker)