def test_block_bodies_msg_from_bodies_bytes(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) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block_body = TransientBlockBody(txs, uncles) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) block_bodies_msg = BlockBodiesEthProtocolMessage.from_body_bytes( block_body_bytes) self.assertEqual(1, len(block_bodies_msg.get_blocks())) self.assertEqual(1, len(block_bodies_msg.get_block_bodies_bytes())) self.assertEqual(block_body, block_bodies_msg.get_blocks()[0]) self.assertEqual(block_body_bytes, block_bodies_msg.get_block_bodies_bytes()[0])
async def test_subscription(self): tx_hash = helpers.generate_object_hash() tx_contents = mock_eth_messages.get_dummy_transaction(1) transaction_key = self.gateway_node.get_tx_service( ).get_transaction_key(tx_hash) self.gateway_node.get_tx_service().set_transaction_contents_by_key( transaction_key, rlp.encode(tx_contents)) tx_hash_2 = helpers.generate_object_hash() tx_contents_2 = mock_eth_messages.get_dummy_transaction(2) transaction_key_2 = self.gateway_node.get_tx_service( ).get_transaction_key(tx_hash_2) self.gateway_node.get_tx_service().set_transaction_contents_by_key( transaction_key_2, rlp.encode(tx_contents_2)) await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash_2.binary)}")) await asyncio.sleep(0.01) self.assertEqual(2, self.subscriber.messages.qsize()) tx_message_1 = await self.subscriber.receive() self.assertEqual(f"0x{convert.bytes_to_hex(tx_hash.binary)}", tx_message_1["tx_hash"]) self.assertEqual(tx_contents.to_json(), tx_message_1["tx_contents"]) tx_message_2 = await self.subscriber.receive() self.assertEqual(f"0x{convert.bytes_to_hex(tx_hash_2.binary)}", tx_message_2["tx_hash"]) self.assertEqual(tx_contents_2.to_json(), tx_message_2["tx_contents"])
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_new_block_internal_eth_message_to_from_new_block_parts(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_number = 100000 block_body = TransientBlockBody(txs, uncles) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) new_block_parts = NewBlockParts(block_header_bytes, block_body_bytes, block_number) new_block_internal_eth_msg = InternalEthBlockInfo.from_new_block_parts( new_block_parts) self.assertIsNotNone(new_block_internal_eth_msg) self.assertTrue(new_block_internal_eth_msg.rawbytes()) parsed_new_block_parts = new_block_internal_eth_msg.to_new_block_parts( ) self.assertIsInstance(parsed_new_block_parts, NewBlockParts) self.assertEqual(block_header_bytes, parsed_new_block_parts.block_header_bytes) self.assertEqual(block_body_bytes, parsed_new_block_parts.block_body_bytes) self.assertEqual(block_number, parsed_new_block_parts.block_number)
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))
async def test_disconnect_server_revive(self): tx_hash = helpers.generate_object_hash() tx_contents = mock_eth_messages.get_dummy_transaction(1) transaction_key = self.gateway_node.get_tx_service( ).get_transaction_key(tx_hash) self.gateway_node.get_tx_service().set_transaction_contents_by_key( transaction_key, rlp.encode(tx_contents)) self.eth_test_ws_server.close() await self.eth_test_ws_server.wait_closed() await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await self.eth_ws_proxy_publisher.close() await asyncio.sleep(0.05) self.assertEqual(0, self.subscriber.messages.qsize()) self.assertFalse(self.eth_ws_proxy_publisher.running) await self.start_server() await asyncio.sleep(0) await self.eth_ws_proxy_publisher.revive() await self.eth_ws_server_message_queue.put( (TX_SUB_ID, f"0x{convert.bytes_to_hex(tx_hash.binary)}")) await asyncio.sleep(0.01) self.assertEqual(1, self.subscriber.messages.qsize())
def get_unsigned(self) -> bytes: if self.is_eip_155_signed(): parts = rlp.decode(rlp.encode(self)) parts_for_signing = parts[:-3] + [eth_common_utils.int_to_big_endian(self.chain_id()), b'', b''] return rlp.encode(parts_for_signing) else: return rlp.encode( UnsignedTransaction( self.nonce, self.gas_price, self.start_gas, self.to, self.value, self.data ) )
def test_block_bodies_msg__get_block_transactions(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(LegacyTransaction.serialize(tx)) txs_bytes.append(tx_bytes) tx_hash = tx.hash() txs_hashes.append(tx_hash) al_tx = mock_eth_messages.get_dummy_access_list_transaction(11) txs.append(al_tx) txs_bytes.append(Transaction.serialize(al_tx)) txs_hashes.append(al_tx.hash()) uncles = [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3), ] block_body = TransientBlockBody(txs, uncles) block_body_bytes = rlp.encode(block_body) block_bodies_msg = BlockBodiesEthProtocolMessage.from_body_bytes( block_body_bytes) parsed_txs_bytes = block_bodies_msg.get_block_transaction_bytes(0) self.assertEqual(len(parsed_txs_bytes), len(txs_hashes)) for index, parsed_tx_bytes in enumerate(parsed_txs_bytes): self.assertEqual( convert.bytes_to_hex(txs_bytes[index]), convert.bytes_to_hex(parsed_tx_bytes), f"failed at index {index}", ) parsed_txs_hashes = block_bodies_msg.get_block_transaction_hashes(0) self.assertEqual(len(parsed_txs_hashes), len(txs_hashes)) for index, parsed_tx_hash in enumerate(parsed_txs_hashes): self.assertEqual(parsed_tx_hash, txs_hashes[index])
def test_legacy_transaction_eip_2718_from_bytes(self): transaction = Transaction.deserialize( eth_fixtures.LEGACY_TRANSACTION_EIP_2718) re_encoded = rlp.encode(transaction) self.assertEqual( Transaction.deserialize(eth_fixtures.LEGACY_TRANSACTION), transaction) self.assertEqual(transaction, rlp.decode(re_encoded, Transaction))
def serialize(cls, obj, type_parsed: bool = False, **kwargs): if type_parsed: result = super().serialize(obj) if obj.transaction_type == EthTransactionType.LEGACY: return result return obj.transaction_type.encode_rlp() + rlp.encode(result) else: return obj.__class__.serialize(obj, type_parsed=True, **kwargs)
def get_unsigned(self) -> bytes: """ Returns unsigned transaction. EIP-2930 transaction are always EIP-155 protected. They do not require any of the v/r/s values included. :return: """ parts = rlp.decode(Transaction.serialize(self)[1:]) return EthTransactionType.ACCESS_LIST.encode_rlp() + rlp.encode( parts[:-3])
def get_encoded_msg_type(self): """ Returns RLP-encoded message type :return: bytes of RLP-encoded message type """ if self._sequence_id and self._sequence_id > 0: return b"" return rlp.encode(self._msg_type, sedes=rlp.sedes.big_endian_int) # unsigned byte
def get_unsigned(self) -> bytes: """ Returns unsigned transaction. EIP-155 protected transactions require the chain ID encoded in the v field, and the r/s fields to be empty. :return: """ if self.is_eip_155_signed(): parts = rlp.decode(rlp.encode(Transaction.serialize(self))) parts_for_signing = parts[:-3] + [ eth_common_utils.int_to_big_endian(self.chain_id()), b"", b"", ] return rlp.encode(parts_for_signing) else: return rlp.encode( UnsignedTransaction(self.nonce, self.gas_price, self.start_gas, self.to, self.value, self.data))
def _serialize_rlp_payload(self): field_values = [getattr(self, field) for field, _ in self.fields] # get single value if message has just one field if len(field_values) == 1: field_values = field_values[0] payload = self._get_serializer().serialize(field_values) encoded_payload = rlp.encode(payload) return encoded_payload
def normalize_typed_transaction(tx_bytes: memoryview) -> memoryview: """ RLP could be either [transaction_type][encoded transaction], or RLP([transaction_type][encoded transaction]). The first form cannot be `rlp.decode`d, as it will only return the transaction type or throw an exception if strict=True. Force it to be of the second type. """ item_type, item_length, _item_start = rlp_utils.consume_length_prefix(tx_bytes, 0) if item_type == str and item_length == 1: tx_bytes = memoryview(rlp.encode(tx_bytes.tobytes())) return tx_bytes
def test_new_block_parts(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_number = 100000 block_body = TransientBlockBody(txs, uncles) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_body_bytes = memoryview( rlp.encode(TransientBlockBody.serialize(block_body))) new_block_parts = NewBlockParts(block_header_bytes, block_body_bytes, block_number) self.assertIsInstance(new_block_parts.get_block_hash(), Sha256Hash) self.assertIsInstance(new_block_parts.get_previous_block_hash(), Sha256Hash) self.assertEqual(1, new_block_parts.get_block_difficulty())
def test_msg_confirmed_tx(self): self.node.feed_manager.publish_to_feed = MagicMock() tx_hash = helpers.generate_object_hash() message = ConfirmedTxMessage(tx_hash) self.connection.msg_confirmed_tx(message) self.node.feed_manager.publish_to_feed.assert_not_called() tx_hash = helpers.generate_object_hash() message = ConfirmedTxMessage( tx_hash, rlp.encode(mock_eth_messages.get_dummy_transaction(1))) self.connection.msg_confirmed_tx(message) self.node.feed_manager.publish_to_feed.assert_called_once()
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 _create_block_header_bytes(self, block_number: int, difficulty: int) -> memoryview: block_header = BlockHeader( helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.ADDRESS_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), 100, difficulty, block_number, 3, 4, 1601410624, helpers.generate_bytes(100), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(12345)) block_header_bytes = rlp.encode(block_header, BlockHeader) return memoryview(block_header_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 test_legacy_transaction_from_bytes(self): transaction = rlp.decode(eth_fixtures.LEGACY_TRANSACTION, Transaction) re_encoded = rlp.encode(transaction) self.assertEqual(transaction, rlp.decode(re_encoded, Transaction)) self.assertEqual(EthTransactionType.LEGACY, transaction.transaction_type) self.assertIsInstance(transaction, LegacyTransaction) self.assertEqual( Sha256Hash.from_string(eth_fixtures.LEGACY_TRANSACTION_HASH), transaction.hash(), ) self.assertEqual("0xc296825bf94ca41b881390955c2731c1d3eaa059", transaction.from_address()) self.assertEqual(37, transaction.v)
def test_block_headers_msg_from_header_bytes(self): block_header = mock_eth_messages.get_dummy_block_header(1) block_header_bytes = memoryview( rlp.encode(BlockHeader.serialize(block_header))) block_headers_msg = BlockHeadersEthProtocolMessage.from_header_bytes( block_header_bytes) raw_headers = block_headers_msg.get_block_headers() headers_list = list(raw_headers) self.assertEqual(len(headers_list), 1) self.assertTrue(headers_list) self.assertEqual(1, len(block_headers_msg.get_block_headers())) self.assertEqual(1, len(block_headers_msg.get_block_headers_bytes())) self.assertEqual(block_header, block_headers_msg.get_block_headers()[0]) self.assertEqual( block_header_bytes.tobytes(), block_headers_msg.get_block_headers_bytes()[0].tobytes())
def test_access_list_transaction_from_bytes(self): transaction: Transaction = rlp.decode(eth_fixtures.ACL_TRANSACTION, Transaction) re_encoded = rlp.encode(transaction) self.assertEqual(transaction, rlp.decode(re_encoded, Transaction)) self.assertEqual(EthTransactionType.ACCESS_LIST, transaction.transaction_type) self.assertIsInstance(transaction, AccessListTransaction) self.assertEqual( Sha256Hash.from_string(eth_fixtures.ACL_TRANSACTION_HASH), transaction.hash(), ) self.assertEqual(1, transaction.chain_id()) self.assertEqual(0, transaction.v) self.assertEqual("0x0087c5900b9bbc051b5f6299f5bce92383273b28", transaction.from_address()) self.assertEqual(3, len(transaction.access_list))
def test_bx_tx_to_tx__success(self): tx = mock_eth_messages.get_dummy_transaction(1) tx_bytes = rlp.encode(tx, Transaction) tx_hash_bytes = hashlib.sha256(tx_bytes).digest() tx_hash = Sha256Hash(tx_hash_bytes) bx_tx_message = TxMessage(message_hash=tx_hash, network_num=self.test_network_num, tx_val=tx_bytes) tx_message = self.eth_message_converter.bx_tx_to_tx(bx_tx_message) self.assertIsNotNone(tx_message) self.assertIsInstance(tx_message, TransactionsEthProtocolMessage) self.assertTrue(tx_message.get_transactions()) self.assertEqual(1, len(tx_message.get_transactions())) tx_obj = tx_message.get_transactions()[0] self.assertEqual(tx, tx_obj)
def get_header(self): """ Returns frame header header: frame-size || header-data || padding frame-size: 3-byte integer size of frame, big endian encoded header-data: normal: rlp.list(protocol-type[, sequence-id]) chunked-0: rlp.list(protocol-type, sequence-id, total-packet-size) chunked-n: rlp.list(protocol-type, sequence-id) normal, chunked-n: rlp.list(protocol-type[, sequence-id]) values: protocol-type: < 2**16 sequence-id: < 2**16 (this value is optional for normal frames) total-packet-size: < 2**32 padding: zero-fill to 16-byte boundary :return: frame header bytes """ header_parts = [self._protocol_id] if self._is_chunked and self._sequence_id == 0: header_parts.append(self._sequence_id) header_parts.append(self._total_payload_size) elif self._sequence_id is not None: # normal, chunked_n header_parts.append(self._sequence_id) header_data = rlp.encode(header_parts, sedes=self.header_data_serializer) # write body_size to header # frame-size: 3-byte integer size of frame, big endian encoded (excludes padding) # frame relates to body w/o padding w/o mac body_size = self.get_body_size() assert body_size < eth_common_constants.FRAME_MAX_BODY_SIZE header = struct.pack(">I", body_size)[1:] + header_data header = crypto_utils.right_0_pad_16(header) # padding assert len(header) == eth_common_constants.FRAME_HDR_DATA_LEN return header
def contents(self) -> memoryview: return memoryview(rlp.encode(self))
def hash_object(self) -> Sha256Hash: return Sha256Hash(eth_common_utils.keccak_hash(rlp.encode(self)))
def test_bx_block_to_block__full_txs_success(self): tx_count = 150 txs = [] short_txs = [] short_ids = [] for i in range(1, tx_count): tx = mock_eth_messages.get_dummy_transaction(1) txs.append(tx) tx_bytes = rlp.encode(tx, Transaction) if i % 2 == 0: tx_hash = hashlib.sha256(tx_bytes).digest() self.tx_service.assign_short_id(tx_hash, i) self.tx_service.set_transaction_contents(tx_hash, tx_bytes) short_tx = ShortTransaction(0, bytes()) short_txs.append(short_tx) short_ids.append(i) else: short_tx = ShortTransaction(1, tx_bytes) short_txs.append(short_tx) dummy_chain_difficulty = 20 dummy_block_number = 10 compact_block = CompactBlock(mock_eth_messages.get_dummy_block_header(8), short_txs, [ mock_eth_messages.get_dummy_block_header(2), mock_eth_messages.get_dummy_block_header(3) ], dummy_chain_difficulty, dummy_block_number) compact_block_msg_bytes = bytearray(constants.UL_ULL_SIZE_IN_BYTES) compact_block_msg_bytes.extend(rlp.encode(compact_block, CompactBlock)) short_ids_offset = len(compact_block_msg_bytes) struct.pack_into("<Q", compact_block_msg_bytes, 0, short_ids_offset) compact_block_bytes = compact_block_short_ids_serializer.serialize_short_ids_into_bytes(short_ids) compact_block_msg_bytes.extend(compact_block_bytes) compact_block_hash_bytes = hashlib.sha256(compact_block_msg_bytes).digest() compact_block_hash = Sha256Hash(compact_block_hash_bytes) bx_block_msg = BroadcastMessage(compact_block_hash, self.test_network_num, is_encrypted=True, blob=compact_block_msg_bytes) block_msg, block_info, unknown_tx_sids, unknown_tx_hashes = self.eth_message_converter.bx_block_to_block( bx_block_msg.blob(), self.tx_service) self.assertTrue(block_msg) self.assertIsInstance(block_msg, InternalEthBlockInfo) new_block_msg = block_msg.to_new_block_msg() block = new_block_msg.get_block() 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 block_tx, i in zip(block.transactions, range(0, tx_count - 1)): self.assertIsInstance(block_tx, Transaction) self._assert_values_equal(block_tx, txs[i]) self.assertEqual(compact_block.chain_difficulty, new_block_msg.chain_difficulty)
def hash(self): hash_bytes = eth_common_utils.keccak_hash(rlp.encode(self)) return Sha256Hash(hash_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)