def test_message_tracked_correctly_when_framed(self): block_stats.add_block_event_by_block_hash = MagicMock() # send the handshake message self.node.on_bytes_sent(self.connection_fileno, 307) self.node.on_bytes_written_to_socket(self.connection_fileno, 307) block_message = NewBlockEthProtocolMessage( None, mock_eth_messages.get_dummy_block( 1, mock_eth_messages.get_dummy_block_header(5, int(time.time()))), 10) block_message.serialize() self.connection.enqueue_msg(block_message) message_length = self.connection.outputbuf.length for message in self.connection.message_tracker.messages: print(message.length) block_stats.add_block_event_by_block_hash.assert_not_called() self.assertEqual(message_length, self.connection.message_tracker.messages[0].length) self.node.on_bytes_sent(self.connection_fileno, message_length) self.node.on_bytes_written_to_socket(self.connection_fileno, message_length) block_stats.add_block_event_by_block_hash.assert_called_once()
def test_bdn_stats_block_new_from_node_ignore_duplicate(self): block_msg = NewBlockEthProtocolMessage( None, _block_with_timestamp( time.time() + 1 - self.node.opts.blockchain_ignore_block_interval_count * self.node.opts.blockchain_block_interval), 10) block_msg.serialize() self.block_blockchain_connection_protocol.msg_block(block_msg) self.block_blockchain_connection_protocol.msg_block(block_msg) self.assertEqual( 3, len(gateway_bdn_performance_stats_service.interval_data. blockchain_node_to_bdn_stats)) node_1_stats = gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats[ self.node_1_endpoint] for endpoint, stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.items( ): if endpoint == self.node_1_endpoint: continue self.assertEqual(1, stats.new_blocks_received_from_bdn) self.assertEqual(1, node_1_stats.new_blocks_received_from_blockchain_node)
def test_bdn_stats_block_new_from_bdn_ignore_from_node(self): block_msg = NewBlockEthProtocolMessage( None, _block_with_timestamp(time.time() + 1 - ( self.node.opts.blockchain_ignore_block_interval_count * self.node.opts.blockchain_block_interval)), 10) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg( block_msg) msg_bytes, block_info = self.node.message_converter.block_to_bx_block( internal_new_block_msg, self.node._tx_service, True, self.node.network.min_tx_age_seconds) msg_hash = Sha256Hash(crypto.double_sha256(msg_bytes)) broadcast_msg = BroadcastMessage(message_hash=msg_hash, network_num=1, is_encrypted=False, blob=msg_bytes) self.relay_connection.msg_broadcast(broadcast_msg) block_msg.serialize() self.block_blockchain_connection_protocol.msg_block(block_msg) self.assertEqual( 3, len(gateway_bdn_performance_stats_service.interval_data. blockchain_node_to_bdn_stats)) for stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.values( ): self.assertEqual(1, stats.new_blocks_received_from_bdn) self.assertEqual(0, stats.new_blocks_received_from_blockchain_node)
def test_block_to_bx_block__empty_block_success(self): block = Block(mock_eth_messages.get_dummy_block_header(8), [], []) dummy_chain_difficulty = 10 block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty) self.assertTrue(block_msg.rawbytes()) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(block_msg) bx_block_msg, block_info = self.eth_message_converter.block_to_bx_block( internal_new_block_msg, self.tx_service, True, 0 ) self.assertEqual(0, block_info.txn_count) self.assertEqual(convert.bytes_to_hex(block.header.prev_hash), block_info.prev_block_hash) self.assertTrue(bx_block_msg) self.assertIsInstance(bx_block_msg, memoryview) block_offsets = compact_block_short_ids_serializer.get_bx_block_offsets(bx_block_msg) _, short_ids_len = compact_block_short_ids_serializer.deserialize_short_ids_from_buffer( bx_block_msg, block_offsets.short_id_offset ) compact_block = rlp.decode( bx_block_msg[block_offsets.block_begin_offset: block_offsets.short_id_offset].tobytes(), CompactBlock ) self.assertTrue(compact_block) self.assertIsInstance(compact_block, CompactBlock) self._assert_values_equal(compact_block.header, block.header) self.assertEqual(0, len(compact_block.uncles)) self.assertEqual(0, len(compact_block.transactions)) self.assertEqual(compact_block.chain_difficulty, block_msg.chain_difficulty)
def msg_block(self, msg: NewBlockEthProtocolMessage): if not self.node.should_process_block_hash(msg.block_hash()): return self.node.set_known_total_difficulty(msg.block_hash(), msg.chain_difficulty()) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(msg) super().msg_block(internal_new_block_msg)
def generate_new_eth_block(self) -> NewBlockEthProtocolMessage: block_message = NewBlockEthProtocolMessage( None, mock_eth_messages.get_dummy_block(1, mock_eth_messages.get_dummy_block_header(5, int(time.time()))), 10 ) block_message.serialize() return block_message
def from_new_block_msg( cls, new_block_msg: NewBlockEthProtocolMessage ) -> "InternalEthBlockInfo": """ Creates NewBlockInternalEthMessage from raw bytes of NewBlockEthProtocolMessage :param new_block_msg: new block message :return: NewBlockInternalEthMessage message """ new_block_msg_bytes = memoryview(new_block_msg.rawbytes()) _, block_msg_itm_len, block_msg_itm_start = rlp_utils.consume_length_prefix( new_block_msg_bytes, 0) block_msg_bytes = new_block_msg_bytes[ block_msg_itm_start:block_msg_itm_start + block_msg_itm_len] msg_size = 0 # block item already include header, transactions and uncles _, block_itm_len, block_itm_start = rlp_utils.consume_length_prefix( block_msg_bytes, 0) block_itm_bytes = block_msg_bytes[ block_msg_itm_start:block_msg_itm_start + block_itm_len] msg_size += len(block_itm_bytes) difficulty_bytes = block_msg_bytes[block_msg_itm_start + block_itm_len:] msg_size += len(difficulty_bytes) block_number_bytes = rlp_utils.encode_int(new_block_msg.number()) msg_size += len(block_number_bytes) msg_prefix = rlp_utils.get_length_prefix_list( len(block_itm_bytes) + len(difficulty_bytes) + len(block_number_bytes)) msg_size += len(msg_prefix) msg_bytes = bytearray(msg_size) written_bytes = 0 msg_bytes[written_bytes:written_bytes + len(msg_prefix)] = msg_prefix written_bytes += len(msg_prefix) msg_bytes[written_bytes:written_bytes + len(block_itm_bytes)] = block_itm_bytes written_bytes += len(block_itm_bytes) msg_bytes[written_bytes:written_bytes + len(difficulty_bytes)] = difficulty_bytes written_bytes += len(difficulty_bytes) msg_bytes[written_bytes:written_bytes + len(block_number_bytes)] = block_number_bytes written_bytes += len(block_number_bytes) assert written_bytes == msg_size return cls(msg_bytes)
def test_msg_block_in_recovery(self): message = NewBlockEthProtocolMessage( None, _block_with_timestamp(time.time()), 10) self.node.block_recovery_service.add_block(message.rawbytes(), message.block_hash(), [1], []) self.sut.msg_block(message) self.node.block_processing_service.queue_block_for_processing.assert_not_called( )
def clean_block_transactions( self, block_msg: NewBlockEthProtocolMessage, transaction_service: TransactionService) -> None: block_hash = block_msg.block_hash() transactions_list = block_msg.txns() self.clean_block_transactions_by_block_components( block_hash=block_hash, transactions_list=(tx.hash() for tx in transactions_list), transaction_service=transaction_service)
def generate_new_eth_block(self, block_number=10) -> InternalEthBlockInfo: block_message = NewBlockEthProtocolMessage( None, mock_eth_messages.get_dummy_block( 1, mock_eth_messages.get_dummy_block_header( 5, int(time.time()), block_number=block_number)), 10) block_message.serialize() internal_block_message = InternalEthBlockInfo.from_new_block_msg( block_message) return internal_block_message
def test_msg_block_too_old(self): message = NewBlockEthProtocolMessage( None, _block_with_timestamp( time.time() - 1 - self.node.opts.blockchain_ignore_block_interval_count * self.node.opts.blockchain_block_interval ), 10 ) message.serialize() self.sut.msg_block(message) self.node.block_processing_service.queue_block_for_processing.assert_not_called()
def msg_block(self, msg: NewBlockEthProtocolMessage) -> None: if not self.node.should_process_block_hash(msg.block_hash()): return self.node.set_known_total_difficulty(msg.block_hash(), msg.get_chain_difficulty()) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(msg) self.process_msg_block(internal_new_block_msg, msg.number()) if self.node.opts.filter_txs_factor > 0: self.node.on_transactions_in_block(msg.txns())
def test_block_to_bx_block_then_bx_block_to_block__success(self): txs = [] txs_bytes = [] txs_hashes = [] short_ids = [] tx_count = 150 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(i) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) self.tx_service.assign_short_id(tx_hash, i) self.tx_service.set_transaction_contents(tx_hash, tx_bytes) short_ids.append(i) block = Block(mock_eth_messages.get_dummy_block_header(100), txs, [mock_eth_messages.get_dummy_block_header(2)]) dummy_chain_difficulty = 40000000 block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty) block_msg_bytes = block_msg.rawbytes() self.assertTrue(block_msg_bytes) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg( block_msg) bx_block_msg, block_info = self.eth_message_converter.block_to_bx_block( internal_new_block_msg, self.tx_service, True, 0) self.assertIsNotNone(bx_block_msg) self.assertEqual(len(txs), block_info.txn_count) self.assertEqual(convert.bytes_to_hex(block.header.prev_hash), block_info.prev_block_hash) converted_block_msg, _, _, _ = self.eth_message_converter.bx_block_to_block( bx_block_msg, self.tx_service) self.assertIsNotNone(converted_block_msg) converted_new_block_msg = converted_block_msg.to_new_block_msg() converted_block_msg_bytes = converted_new_block_msg.rawbytes() self.assertEqual(len(converted_block_msg_bytes), len(block_msg_bytes)) self.assertEqual(converted_block_msg_bytes, block_msg_bytes)
def test_new_block_internal_eth_message_to_from_new_block_message(self): txs = [] txs_bytes = [] txs_hashes = [] tx_count = 10 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) block_header = mock_eth_messages.get_dummy_block_header(1) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block = Block(block_header, txs, uncles) dummy_chain_difficulty = 10 block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty) self.assertTrue(block_msg.rawbytes()) new_block_internal_eth_msg = InternalEthBlockInfo.from_new_block_msg( block_msg) self.assertIsNotNone(new_block_internal_eth_msg) self.assertTrue(new_block_internal_eth_msg.rawbytes()) parsed_new_block_message = new_block_internal_eth_msg.to_new_block_msg( ) self.assertIsInstance(parsed_new_block_message, NewBlockEthProtocolMessage) self.assertEqual(len(block_msg.rawbytes()), len(parsed_new_block_message.rawbytes())) self.assertEqual( convert.bytes_to_hex(block_msg.rawbytes()), convert.bytes_to_hex(parsed_new_block_message.rawbytes()), )
def _get_sample_block(self, file_path): root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(file_path)))) with open(os.path.join(root_dir, "samples/eth_sample_block.txt")) as sample_file: btc_block = sample_file.read().strip("\n") buf = bytearray(convert.hex_to_bytes(btc_block)) parsed_block = NewBlockEthProtocolMessage(msg_bytes=buf) return parsed_block
def test_msg_get_block_headers_block_number(self): block_number = 123456 header = mock_eth_messages.get_dummy_block_header( 12, block_number=block_number ) block = mock_eth_messages.get_dummy_block(1, header) block_hash = header.hash_object() new_block_message = NewBlockEthProtocolMessage(None, block, 10) eth_block_info = InternalEthBlockInfo.from_new_block_msg( new_block_message ) self.node.block_queuing_service_manager.push(block_hash, eth_block_info) self.enqueued_messages.clear() self.sut.msg_proxy_request = MagicMock() block_number_bytes = struct.pack(">I", block_number) message = GetBlockHeadersEthProtocolMessage( None, block_number_bytes, 1, 0, 0 ) self.sut.msg_get_block_headers(message) self.sut.msg_proxy_request.assert_not_called() self.assertEqual(1, len(self.enqueued_messages)) headers_sent = self.enqueued_messages[0] self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage) self.assertEqual(1, len(headers_sent.get_block_headers())) self.assertEqual( block_hash, headers_sent.get_block_headers()[0].hash_object() )
def test_msg_get_block_headers_known_single(self): header = mock_eth_messages.get_dummy_block_header(12) block = mock_eth_messages.get_dummy_block(1, header) raw_hash = header.hash() block_hash = header.hash_object() new_block_message = NewBlockEthProtocolMessage(None, block, 10) eth_block_info = InternalEthBlockInfo.from_new_block_msg( new_block_message ) self.node.block_queuing_service_manager.push(block_hash, eth_block_info) self.enqueued_messages.clear() self.sut.msg_proxy_request = MagicMock() message = GetBlockHeadersEthProtocolMessage(None, raw_hash, 1, 0, 0) self.sut.msg_get_block_headers(message) self.sut.msg_proxy_request.assert_not_called() self.assertEqual(1, len(self.enqueued_messages)) headers_sent = self.enqueued_messages[0] self.assertIsInstance(headers_sent, BlockHeadersEthProtocolMessage) self.assertEqual(1, len(headers_sent.get_block_headers())) self.assertEqual( block_hash, headers_sent.get_block_headers()[0].hash_object() ) self.block_queuing_service.mark_block_seen_by_blockchain_node( block_hash, eth_block_info ) self.sut.msg_get_block_headers(message) self.sut.msg_proxy_request.assert_not_called() self.assertEqual(2, len(self.enqueued_messages))
def new_block_eth_protocol_message( nonce: int, block_number: Optional[int] = None, prev_block_hash: Optional[Sha256Hash] = None ) -> NewBlockEthProtocolMessage: header = get_dummy_block_header(nonce, block_number=block_number, prev_block_hash=prev_block_hash) block = get_dummy_block(nonce, header) return NewBlockEthProtocolMessage(None, block, nonce * 5 + 10)
async def test_eth_transaction_receipts_feed_specify_include(self): self.gateway_node.opts.eth_ws_uri = f"ws://{constants.LOCALHOST}:8005" self.gateway_node.feed_manager.register_feed( EthTransactionReceiptsFeed(self.gateway_node, 0)) self.gateway_node.eth_ws_proxy_publisher = MockEthWsProxyPublisher( "", None, None, self.gateway_node) receipt_response = { "blockHash": "0xe6f67c6948158c45dct10b169ad6bf3a96c6402489733a03051feaf7d09e7b54", "blockNumber": "0xaf25e5", "cumulativeGasUsed": "0xbdb9ae", "from": "0x82170dd1cec50107963bf1ba1e80955ea302c5ce", "gasUsed": "0x5208", "logs": [], "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "status": "0x1", "to": "0xa09f63d9a0b0fbe89e41e51282ad660e7c876165", "transactionHash": "0xbcdc5b22bf463f9b8766dd61cc133caf13472b6ae8474061134d9dc2983625f6", "transactionIndex": "0x90" } receipt_result = { "transactionHash": "0xbcdc5b22bf463f9b8766dd61cc133caf13472b6ae8474061134d9dc2983625f6" } self.gateway_node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1, result=receipt_response)) block = mock_eth_messages.get_dummy_block(5) internal_block_info = InternalEthBlockInfo.from_new_block_msg( NewBlockEthProtocolMessage(None, block, 1)) eth_raw_block = EthRawBlock( 1, internal_block_info.block_hash(), FeedSource.BLOCKCHAIN_RPC, get_block_message_lazy(internal_block_info)) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME, {"include": ["receipt.transaction_hash"]}) self.gateway_node.feed_manager.publish_to_feed( FeedKey(rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME), eth_raw_block) for i in range(len(block.transactions)): subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(subscription_message.notification, {"receipt": receipt_result})
def send_block_to_node( self, block_hash: Sha256Hash, block_msg: Optional[InternalEthBlockInfo] = None, ) -> None: assert block_msg is not None # block must always be greater than previous best block_number = block_msg.block_number() best_height, _best_hash, _ = self.best_sent_block assert block_number > best_height new_block_parts = self.node.block_parts_storage[block_hash] if block_msg.has_total_difficulty(): new_block_msg = block_msg.to_new_block_msg() super(EthBlockQueuingService, self).send_block_to_node(block_hash, new_block_msg) self.node.set_known_total_difficulty( new_block_msg.block_hash(), new_block_msg.get_chain_difficulty()) else: calculated_total_difficulty = self.node.try_calculate_total_difficulty( block_hash, new_block_parts) if calculated_total_difficulty is None: # Total difficulty may be unknown after a long fork or # if gateways just started. Announcing new block hashes to # ETH node in that case. It # will request header and body separately. new_block_headers_msg = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair( block_hash, new_block_parts.block_number) super(EthBlockQueuingService, self).send_block_to_node(block_hash, new_block_headers_msg) else: new_block_msg = NewBlockEthProtocolMessage.from_new_block_parts( new_block_parts, calculated_total_difficulty) super(EthBlockQueuingService, self).send_block_to_node(block_hash, new_block_msg) self.node.log_blocks_network_content(self.node.network_num, block_msg) self.sent_block_at_height[block_number] = block_hash self.best_sent_block = SentEthBlockInfo(block_number, block_hash, time.time()) self._schedule_confirmation_check(block_hash) if self.node.opts.filter_txs_factor > 0: self.node.on_transactions_in_block( block_msg.to_new_block_msg().txns())
def test_new_block_parts_to_new_block_message(self): txs = [] txs_bytes = [] txs_hashes = [] tx_count = 10 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) block_header = mock_eth_messages.get_dummy_block_header(1) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block = Block(block_header, txs, uncles) dummy_chain_difficulty = 10 new_block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty) self.assertTrue(new_block_msg.rawbytes()) block_body = TransientBlockBody(txs, uncles) block_bytes = rlp.encode(Block.serialize(block)) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) self.assertEqual(len(block_bytes), len(block_header_bytes) + len(block_body_bytes)) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg( new_block_msg) new_block_parts = internal_new_block_msg.to_new_block_parts() new_block_msg_from_block_parts = NewBlockEthProtocolMessage.from_new_block_parts( new_block_parts, dummy_chain_difficulty) self.assertEqual(len(new_block_msg.rawbytes()), len(new_block_msg_from_block_parts.rawbytes())) self.assertEqual(new_block_msg.rawbytes(), new_block_msg_from_block_parts.rawbytes()) self.assertEqual(new_block_msg_from_block_parts.get_chain_difficulty(), dummy_chain_difficulty)
def test_header_body_fetch_abort_from_bdn(self): self.node.block_processing_service.queue_block_for_processing = MagicMock() self.sut.is_valid_block_timestamp = MagicMock(return_value=True) header = mock_eth_messages.get_dummy_block_header(1) block = mock_eth_messages.get_dummy_block(1, header) block_hash = header.hash_object() new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair( block_hash, 1 ) header_message = BlockHeadersEthProtocolMessage(None, [header]) bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)]) internal_block_info = InternalEthBlockInfo.from_new_block_msg(NewBlockEthProtocolMessage(None, block, 1)) self.sut.msg_new_block_hashes(new_block_hashes_message) self.assertEqual(1, len(self.sut.pending_new_block_parts.contents)) self.assertEqual(2, len(self.enqueued_messages)) self.node.on_block_received_from_bdn(block_hash, internal_block_info) self.sut.msg_block_headers(header_message) self.sut.msg_block_bodies(bodies_message) self.node.block_processing_service.queue_block_for_processing.assert_not_called()
def to_new_block_msg(self) -> NewBlockEthProtocolMessage: """ Converts message to instance of NewBlockEthProtocolMessage :return: instance of NewBlockEthProtocolMessage """ _, msg_itm_len, msg_itm_start = rlp_utils.consume_length_prefix( self._memory_view, 0) msg_itm_bytes = self._memory_view[msg_itm_start:] offset = 0 msg_size = 0 _, header_len, header_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) header_bytes = msg_itm_bytes[offset:header_start + header_len] offset = header_start + header_len msg_size += len(header_bytes) _, txs_len, txs_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) txs_bytes = msg_itm_bytes[offset:txs_start + txs_len] offset = txs_start + txs_len msg_size += len(txs_bytes) _, uncles_len, uncles_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) uncles_bytes = msg_itm_bytes[offset:uncles_start + uncles_len] offset = uncles_start + uncles_len msg_size += len(uncles_bytes) _, total_difficulty_len, total_difficulty_start = rlp_utils.consume_length_prefix( msg_itm_bytes, offset) total_difficulty_bytes = msg_itm_bytes[offset:total_difficulty_start + total_difficulty_len] msg_size += len(total_difficulty_bytes) block_prefix = rlp_utils.get_length_prefix_list( len(header_bytes) + len(txs_bytes) + len(uncles_bytes)) msg_size += len(block_prefix) msg_prefix = rlp_utils.get_length_prefix_list(msg_size) msg_size += len(msg_prefix) result_msg_bytes = bytearray(msg_size) written_bytes = 0 result_msg_bytes[written_bytes:written_bytes + len(msg_prefix)] = msg_prefix written_bytes += len(msg_prefix) result_msg_bytes[written_bytes:written_bytes + len(block_prefix)] = block_prefix written_bytes += len(block_prefix) result_msg_bytes[written_bytes:written_bytes + len(header_bytes)] = header_bytes written_bytes += len(header_bytes) result_msg_bytes[written_bytes:written_bytes + len(txs_bytes)] = txs_bytes written_bytes += len(txs_bytes) result_msg_bytes[written_bytes:written_bytes + len(uncles_bytes)] = uncles_bytes written_bytes += len(uncles_bytes) result_msg_bytes[written_bytes:written_bytes + len(total_difficulty_bytes)] = total_difficulty_bytes written_bytes += len(total_difficulty_bytes) assert written_bytes == msg_size return NewBlockEthProtocolMessage(result_msg_bytes)
def test_block_to_bx_block__no_compressed_block(self): txs = [] txs_bytes = [] txs_hashes = [] short_ids = [] used_short_ids = [] tx_count = 150 for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) short_ids.append(0) block = Block( mock_eth_messages.get_dummy_block_header(1), txs, [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] ) dummy_chain_difficulty = 10 block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty) self.assertTrue(block_msg.rawbytes()) internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(block_msg) bx_block_msg, block_info = self.eth_message_converter.block_to_bx_block( internal_new_block_msg, self.tx_service, False, 0 ) self.assertTrue(len(bx_block_msg) >= len(internal_new_block_msg.rawbytes())) self.assertEqual(len(txs), block_info.txn_count) self.assertEqual(convert.bytes_to_hex(block.header.prev_hash), block_info.prev_block_hash) self.assertEqual(used_short_ids, list(block_info.short_ids)) self.assertTrue(bx_block_msg) self.assertIsInstance(bx_block_msg, memoryview) block_offsets = compact_block_short_ids_serializer.get_bx_block_offsets(bx_block_msg) compact_block = rlp.decode( bx_block_msg[block_offsets.block_begin_offset: block_offsets.short_id_offset].tobytes(), CompactBlock ) self.assertTrue(compact_block) self.assertIsInstance(compact_block, CompactBlock) self._assert_values_equal(compact_block.header, block.header) self._assert_values_equal(compact_block.uncles, block.uncles) self.assertEqual(len(compact_block.transactions), len(block.transactions)) for tx, short_tx, i in zip(block.transactions, compact_block.transactions, range(1, tx_count)): self.assertIsInstance(tx, Transaction) self.assertIsInstance(short_tx, ShortTransaction) self.assertEqual(1, short_tx.full_transaction) self.assertEqual(short_tx.transaction_bytes, txs_bytes[i - 1]) self.assertEqual(compact_block.chain_difficulty, block_msg.chain_difficulty) converted_block_msg, _, _, _ = self.eth_message_converter.bx_block_to_block(bx_block_msg, self.tx_service) self.assertIsNotNone(converted_block_msg)