def msg_inv(self, msg: InvOntMessage) -> None: if not self.node.should_process_block_hash(): return contains_block = False inventory_requests = [] block_hashes = [] inventory_type, item_hashes = msg.inv_type() if inventory_type == InventoryOntType.MSG_BLOCK.value: for item_hash in item_hashes: block_hashes.append(item_hash) if item_hash not in self.node.blocks_seen.contents: contains_block = True inventory_requests.append(item_hash) else: for item_hash in item_hashes: inventory_requests.append(item_hash) # TODO: mark_blocks_and_request_cleanup for req in inventory_requests: get_data = GetDataOntMessage( magic=msg.magic(), inv_type=inventory_type, block=req ) self.connection.enqueue_msg(get_data, prepend=contains_block) block_queuing_service = self.node.block_queuing_service_manager.get_block_queuing_service(self.connection) if block_queuing_service is not None: block_queuing_service.mark_blocks_seen_by_blockchain_node(block_hashes)
def _request_block(self, block_hash: Sha256Hash) -> None: block_request_message = GetDataOntMessage( magic=self.node.opts.blockchain_net_magic, inv_type=InventoryOntType.MSG_BLOCK.value, block=block_hash ) self.node.send_msg_to_node(block_request_message) logger.trace("Received block cleanup request: {}", block_hash)
def test_inv_and_get_data(self): seen_block_hash = OntObjectHash(buf=helpers.generate_bytearray(ONT_HASH_LEN), length=ONT_HASH_LEN) not_seen_block_hash = OntObjectHash(buf=helpers.generate_bytearray(ONT_HASH_LEN), length=ONT_HASH_LEN) self.node.blocks_seen.add(seen_block_hash) inv_msg_seen_block = InvOntMessage(123, InventoryOntType.MSG_BLOCK, [seen_block_hash, seen_block_hash]) self.sut.msg_inv(inv_msg_seen_block) get_data_msg_msg_seen_bytes = self.sut.connection.get_bytes_to_send() self.assertEqual(0, len(get_data_msg_msg_seen_bytes)) inv_msg = InvOntMessage(123, InventoryOntType.MSG_BLOCK, [seen_block_hash, not_seen_block_hash]) self.sut.msg_inv(inv_msg) get_data_msg_bytes = self.sut.connection.get_bytes_to_send() get_data_msg = GetDataOntMessage(buf=get_data_msg_bytes) data_msg_inv_type, data_msg_block = get_data_msg.inv_type() self.assertEqual(InventoryOntType.MSG_BLOCK.value, data_msg_inv_type) self.assertEqual(not_seen_block_hash, data_msg_block)
def msg_headers(self, msg: HeadersOntMessage): if not self.node.should_process_block_hash(): return header = msg.headers()[-1] raw_hash = crypto.double_sha256(header) reply = GetDataOntMessage(self.magic, InventoryOntType.MSG_BLOCK.value, OntObjectHash(buf=raw_hash, length=ont_constants.ONT_HASH_LEN)) self.connection.enqueue_msg(reply)
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 msg_get_data(self, msg: GetDataOntMessage) -> None: inventory_type, item_hash = msg.inv_type() if inventory_type == InventoryOntType.MSG_BLOCK.value: block_stats.add_block_event_by_block_hash( item_hash, BlockStatEventType.REMOTE_BLOCK_REQUESTED_BY_GATEWAY, network_num=self.connection.network_num, more_info="Protocol: {}, Network: {}".format( self.node.opts.blockchain_protocol, self.node.opts.blockchain_network)) self.node.block_queuing_service.send_block_to_nodes(item_hash)
def _request_block(self, block_hash: Sha256Hash) -> None: block_request_message = GetDataOntMessage( magic=self.node.opts.blockchain_net_magic, inv_type=InventoryOntType.MSG_BLOCK.value, # pyre-fixme[6]: Expected `[OntObjectHash]` for 3rd parameter but got `Sha256Hash` block=block_hash ) node_conn = typing.cast("bxgateway.connections.ont.ont_node_connection.OntNodeConnection", self.node.get_any_active_blockchain_connection()) if node_conn is None: logger.debug("Request for block '{}' failed. No connection to node.", repr(block_hash)) return node_conn.enqueue_msg(block_request_message) logger.trace("Received block cleanup request: {}", block_hash)
def test_peek_message_success_all_types(self): self.get_message_preview_successfully(self.VERSION_ONT_MESSAGE, VersionOntMessage.MESSAGE_TYPE, 83) self.get_message_preview_successfully( VerAckOntMessage(self.MAGIC, True), VerAckOntMessage.MESSAGE_TYPE, 1) self.get_message_preview_successfully(PingOntMessage(self.MAGIC), PingOntMessage.MESSAGE_TYPE, 8) self.get_message_preview_successfully(PongOntMessage(self.MAGIC, 123), PongOntMessage.MESSAGE_TYPE, 8) self.get_message_preview_successfully(GetAddrOntMessage(self.MAGIC), GetAddrOntMessage.MESSAGE_TYPE, 0) self.get_message_preview_successfully( AddrOntMessage( self.MAGIC, [(int(time.time()), 123, "127.0.0.1", 20300, 20200, 1234)]), AddrOntMessage.MESSAGE_TYPE, 52) self.get_message_preview_successfully( OntConsensusMessage(self.MAGIC, self.VERSION, bytes(20)), OntConsensusMessage.MESSAGE_TYPE, 24) self.get_message_preview_successfully( InvOntMessage(self.MAGIC, InventoryOntType.MSG_TX, [self.HASH, self.HASH]), InvOntMessage.MESSAGE_TYPE, 69) self.get_message_preview_successfully( GetDataOntMessage(self.MAGIC, 1, self.HASH), GetDataOntMessage.MESSAGE_TYPE, 33) self.get_message_preview_successfully( GetHeadersOntMessage(self.MAGIC, 1, self.HASH, self.HASH), GetHeadersOntMessage.MESSAGE_TYPE, 65) self.get_message_preview_successfully( GetBlocksOntMessage(self.MAGIC, 1, self.HASH, self.HASH), GetBlocksOntMessage.MESSAGE_TYPE, 65) self.get_message_preview_successfully( TxOntMessage(self.MAGIC, self.VERSION, bytes(20)), TxOntMessage.MESSAGE_TYPE, 21) self.get_message_preview_successfully( BlockOntMessage(self.MAGIC, self.VERSION, self.HASH, self.HASH, self.HASH, 0, 0, 0, bytes(10), bytes(20), [bytes(33)] * 5, [bytes(2)] * 3, [bytes(32)] * 5, self.HASH), BlockOntMessage.MESSAGE_TYPE, 524) self.get_message_preview_successfully( HeadersOntMessage(self.MAGIC, [bytes(1)] * 2), HeadersOntMessage.MESSAGE_TYPE, 6) self.get_message_preview_successfully( NotFoundOntMessage(self.MAGIC, self.HASH), NotFoundOntMessage.MESSAGE_TYPE, 32)
def test_parse_message_success_all_types(self): self.create_message_successfully(self.VERSION_ONT_MESSAGE, VersionOntMessage) self.create_message_successfully(VerAckOntMessage(self.MAGIC, False), VerAckOntMessage) self.create_message_successfully(PingOntMessage(self.MAGIC), PingOntMessage) self.create_message_successfully(PongOntMessage(self.MAGIC, 123), PongOntMessage) self.create_message_successfully(GetAddrOntMessage(self.MAGIC), GetAddrOntMessage) self.create_message_successfully( AddrOntMessage( self.MAGIC, [(int(time.time()), 123, "127.0.0.1", 20300, 20200, 1234)]), AddrOntMessage) self.create_message_successfully( OntConsensusMessage(self.MAGIC, self.VERSION, bytes(20)), OntConsensusMessage) self.create_message_successfully( InvOntMessage(self.MAGIC, InventoryOntType.MSG_TX, [self.HASH, self.HASH]), InvOntMessage) self.create_message_successfully( GetDataOntMessage(self.MAGIC, 1, self.HASH), GetDataOntMessage) self.create_message_successfully( GetHeadersOntMessage(self.MAGIC, 1, self.HASH, self.HASH), GetHeadersOntMessage) self.create_message_successfully( GetBlocksOntMessage(self.MAGIC, 1, self.HASH, self.HASH), GetBlocksOntMessage) self.create_message_successfully( TxOntMessage(self.MAGIC, self.VERSION, bytes(20)), TxOntMessage) self.create_message_successfully( BlockOntMessage(self.MAGIC, self.VERSION, self.HASH, self.HASH, self.HASH, 0, 0, 0, bytes(10), bytes(20), [bytes(33)] * 5, [bytes(2)] * 3, [bytes(32)] * 5, self.HASH), BlockOntMessage) self.create_message_successfully( HeadersOntMessage(self.MAGIC, [bytes(1)] * 2), HeadersOntMessage) self.create_message_successfully( NotFoundOntMessage(self.MAGIC, self.HASH), NotFoundOntMessage)