async def test_publish_transaction_dictionary(self): subscriber = self.sut.subscribe({}) transaction_hash_str = SAMPLE_TRANSACTION_FROM_WS["hash"] transaction_hash = Sha256Hash( convert.hex_to_bytes(transaction_hash_str[2:])) self.sut.publish( EthRawTransaction(transaction_hash, SAMPLE_TRANSACTION_FROM_WS, FeedSource.BLOCKCHAIN_RPC, local_region=True)) received_tx = await subscriber.receive() self.assertEqual(transaction_hash_str, received_tx["tx_hash"]) self.assertEqual(transaction_hash_str, received_tx["tx_contents"]["hash"]) self.assertIn("from", received_tx["tx_contents"]) self.assertIn("gas", received_tx["tx_contents"]) self.assertIn("gas_price", received_tx["tx_contents"]) self.assertIn("input", received_tx["tx_contents"]) self.assertIn("value", received_tx["tx_contents"]) self.assertIn("to", received_tx["tx_contents"]) self.assertIn("nonce", received_tx["tx_contents"]) self.assertIn("v", received_tx["tx_contents"]) self.assertIn("r", received_tx["tx_contents"]) self.assertIn("s", received_tx["tx_contents"])
def _get_sample_block(self, file_path=__file__): root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(file_path)))) with open(os.path.join(root_dir, "samples/btc_sample_block.txt")) as sample_file: btc_block = sample_file.read().strip("\n") buf = bytearray(convert.hex_to_bytes(btc_block)) parsed_block = BlockBtcMessage(buf=buf) return parsed_block
def get_sample_block(): root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) with open(os.path.join(root_dir, "samples/ont_consensus_sample_block.txt")) as sample_file: ont_block = sample_file.read().strip("\n") buf = bytearray(convert.hex_to_bytes(ont_block)) parsed_block = OntConsensusMessage(buf=buf) return parsed_block
def _test_msg_serialization(self, msg_cls, needs_private_key, *args, **kwargs): if needs_private_key: # random private key private_key = convert.hex_to_bytes( "294549f8629f0eeb2b8e01aca491f701f5386a9662403b485c4efe7d447dfba3" ) msg = msg_cls(None, private_key, *args, **kwargs) else: msg = msg_cls(None, *args, **kwargs) # verify that fields values are set correctly self._verify_field_values(msg_cls, msg, *args) # serialize message into bytes msg_bytes = msg.rawbytes() # deserialize message from bytes msg_deserialized = msg_cls(msg_bytes) msg_deserialized.deserialize() # verify that field values are correct after deserialization self._verify_field_values(msg_cls, msg_deserialized, *args) # verify message serializes print(msg) self.assertEqual(msg.msg_type, msg_cls.msg_type) self.assertEqual(msg.msg_type, msg_deserialized.msg_type)
def setUp(self): self.node = MockGatewayNode( gateway_helpers.get_gateway_opts(8000, include_default_btc_args=True, compact_block_min_tx_count=5)) self.node.block_processing_service = MagicMock() self.connection = BtcNodeConnection( MockSocketConnection(1, node=self.node, ip_address=LOCALHOST, port=123), self.node) self.connection.node = self.node self.connection.peer_ip = LOCALHOST self.connection.peer_port = 8001 self.connection.network_num = 2 self.sut = BtcNodeConnectionProtocol(self.connection) full_block_msg = BlockBtcMessage( buf=bytearray(convert.hex_to_bytes(self.FULL_BLOCK_BYTES_HEX))) if self.node.opts.use_extensions: transaction_service = ExtensionTransactionService(self.node, 0) else: transaction_service = TransactionService(self.node, 0) short_id = 1 for tx in full_block_msg.txns(): tx_hash = btc_common_utils.get_txid(tx) transaction_service.set_transaction_contents(tx_hash, tx) transaction_service.assign_short_id(tx_hash, short_id) short_id += 1 self.sut.connection.node._tx_service = transaction_service
def block_to_bx_block(self, block_msg: BlockOntMessage, tx_service: ExtensionTransactionService) -> \ Tuple[memoryview, BlockInfo]: compress_start_datetime = datetime.utcnow() compress_start_timestamp = time.time() self._default_block_size = max(self._default_block_size, len(block_msg.buf)) tsk = self.compression_tasks.borrow_task() tsk.init(tpe.InputBytes(block_msg.buf), tx_service.proxy) try: task_pool_proxy.run_task(tsk) except tpe.AggregatedException as e: self.compression_tasks.return_task(tsk) raise message_conversion_error.btc_block_compression_error( block_msg.block_hash(), e) bx_block = tsk.bx_block() block = memoryview(bx_block) compressed_size = len(block) original_size = len(block_msg.rawbytes()) block_hash = OntObjectHash( binary=convert.hex_to_bytes(tsk.block_hash().hex_string())) block_info = BlockInfo( block_hash, tsk.short_ids(), compress_start_datetime, datetime.utcnow(), (time.time() - compress_start_timestamp) * 1000, tsk.txn_count(), tsk.compressed_block_hash().hex_string(), tsk.prev_block_hash().hex_string(), original_size, compressed_size, 100 - float(compressed_size) / original_size * 100) self.compression_tasks.return_task(tsk) return block, block_info
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
async def handle_tx_notifications(self, subscription_id: str) -> None: while self.running: next_notification = await self.get_next_subscription_notification_by_id( subscription_id) transaction_hash = next_notification.notification assert isinstance(transaction_hash, str) self.process_received_transaction( Sha256Hash(convert.hex_to_bytes(transaction_hash[2:])))
def test_msg_compact_block_handler(self): message = CompactBlockBtcMessage(buf=bytearray(convert.hex_to_bytes(self.COMPACT_BLOCK_BYTES_HEX))) message._timestamp = int(time.time()) self.assertFalse(message.block_hash() in self.connection.node.blocks_seen.contents) self.node.block_processing_service.process_compact_block.assert_not_called() self.sut.msg_compact_block(message) self.assertTrue(message.block_hash() in self.connection.node.blocks_seen.contents) self.node.block_processing_service.process_compact_block.assert_called_once()
def test_segwit_tx_hash(self): seg_tx = "010000000001024668fcfeba861f7f1bf4d386f15cc6923bd8425e0214686671775359d17a51d50100000000ffffffffdc5530f864de2fac86246426094d7b8586a452d6bd8c209bb891646afb3548770000000000ffffffff0220040000000000001600147771a1cab96e36344b1693d3d9f29180ca900482f5c40100000000001976a91483121cc1ea476c25d91191ff735a5e90518c732788ac02473044022006db5e6aa36dafb5d89a8522675d304a228d39ede1450aaab04f84b1fb57db2902203efb537cca9738c599d95d5c0ddcec6ebd11c6001541a89a468246318e0bd6fe012102d6b8b2ba44eb621ac9537ed7e11553bb02060abca88a9e6faf7697df5ac6d30c02483045022100b04869e06930db5d4e8e4d453d9aed1097a8dae57eef0274ebdc99a106796335022037a6b744900b9b6392448c961e8d793367a0caf675b9ca80349c593e505d8e9d0121034ef9635ae7cd714b2cf8af7e72f23b8b07c7f75d75df95da8d682ae17459091b00000000" seg_tx_bytes = convert.hex_to_bytes(seg_tx) self.assertTrue(btc_common_utils.is_segwit(seg_tx_bytes)) self.assertEqual( convert.bytes_to_hex( btc_common_utils.get_txid(seg_tx_bytes).binary), "d9a057f11a21cf8afd32278e23fd2290660f05a3ffb582466eb5a1a5ece4ce85")
def on_updated_remote_blockchain_peer(self, peer): if "node_public_key" not in peer.attributes: logger.warning(log_messages.BLOCKCHAIN_PEER_LACKS_PUBLIC_KEY) return constants.SDN_CONTACT_RETRY_SECONDS else: super(EthGatewayNode, self).on_updated_remote_blockchain_peer(peer) self._remote_public_key = convert.hex_to_bytes(peer.attributes["node_public_key"]) return constants.CANCEL_ALARMS
def test_non_segwit_tx_hash(self): non_seg_tx = "0100000002d8c8df6a6fdd2addaf589a83d860f18b44872d13ee6ec3526b2b470d42a96d4d000000008b483045022100b31557e47191936cb14e013fb421b1860b5e4fd5d2bc5ec1938f4ffb1651dc8902202661c2920771fd29dd91cd4100cefb971269836da4914d970d333861819265ba014104c54f8ea9507f31a05ae325616e3024bd9878cb0a5dff780444002d731577be4e2e69c663ff2da922902a4454841aa1754c1b6292ad7d317150308d8cce0ad7abffffffff2ab3fa4f68a512266134085d3260b94d3b6cfd351450cff021c045a69ba120b2000000008b4830450220230110bc99ef311f1f8bda9d0d968bfe5dfa4af171adbef9ef71678d658823bf022100f956d4fcfa0995a578d84e7e913f9bb1cf5b5be1440bcede07bce9cd5b38115d014104c6ec27cffce0823c3fecb162dbd576c88dd7cda0b7b32b0961188a392b488c94ca174d833ee6a9b71c0996620ae71e799fc7c77901db147fa7d97732e49c8226ffffffff02c0175302000000001976a914a3d89c53bb956f08917b44d113c6b2bcbe0c29b788acc01c3d09000000001976a91408338e1d5e26db3fce21b011795b1c3c8a5a5d0788ac00000000" non_seg_tx_bytes = convert.hex_to_bytes(non_seg_tx) self.assertFalse(btc_common_utils.is_segwit(non_seg_tx_bytes)) self.assertEqual( convert.bytes_to_hex( btc_common_utils.get_txid(non_seg_tx_bytes).binary), "9021b49d445c719106c95d561b9c3fac7bcb3650db67684a9226cd7fa1e1c1a0")
def _get_sample_block(self): root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) with open(os.path.join(root_dir, "samples/ont_sample_block.txt")) as sample_file: ont_block = sample_file.read().strip("\n") buf = bytearray(convert.hex_to_bytes(ont_block)) parsed_block = BlockOntMessage(buf=buf) self.magic = parsed_block.magic() self.version = parsed_block.version() return parsed_block
def test_status_eth_message(self): dummy_network_id = 111 dummy_chain_difficulty = 11111 dummy_chain_head_hash = convert.hex_to_bytes( "f973c5d3763c40e2b5080f35a9003e64e7d9f9d429ddecd7c559cbd4061094cd") dummy_genesis_hash = convert.hex_to_bytes( "aec175735fb6b74722d54455b638f6340bb9fdd5fa8101c8c0869d10cdccb000") self._test_msg_serialization(StatusEthProtocolMessage, False, eth_common_constants.ETH_PROTOCOL_VERSION, dummy_network_id, dummy_chain_difficulty, dummy_chain_head_hash, dummy_genesis_hash, [b'\xe0)\xe9\x91', 0]) self._test_msg_serialization(StatusEthProtocolMessageV63, False, eth_common_constants.ETH_PROTOCOL_VERSION, dummy_network_id, dummy_chain_difficulty, dummy_chain_head_hash, dummy_genesis_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 from_json(cls, payload: Dict[str, Any]) -> "Transaction": return cls( int(payload["nonce"], 16), int(payload["gasPrice"], 16), int(payload["gas"], 16), utils.or_else( utils.optional_map( payload["to"], lambda to: convert.hex_to_bytes(to[2:]) ), bytes() ), int(payload["value"], 16), convert.hex_to_bytes(payload["input"][2:]), int(payload["v"], 16), int(payload["r"], 16), int(payload["s"], 16), )
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))
async def test_blxr_tx_ethereum_berlin(self): self.gateway_node.message_converter = EthNormalMessageConverter() self.gateway_node.network_num = 5 # legacy result = await self.request( BxJsonRpcRequest( "1", RpcRequestType.BLXR_TX, { rpc_constants.TRANSACTION_PARAMS_KEY: convert.bytes_to_hex(eth_fixtures.LEGACY_TRANSACTION), rpc_constants.STATUS_TRACK_PARAMS_KEY: "True" })) self.assertEqual("1", result.id) self.assertIsNone(result.error) self.assertEqual(eth_fixtures.LEGACY_TRANSACTION_HASH, result.result["tx_hash"]) self.assertEqual(1, len(self.gateway_node.broadcast_messages)) self.assertEqual( Sha256Hash( convert.hex_to_bytes(eth_fixtures.LEGACY_TRANSACTION_HASH)), self.gateway_node.broadcast_messages[0][0].tx_hash()) # access list result = await self.request( BxJsonRpcRequest( "1", RpcRequestType.BLXR_TX, { rpc_constants.TRANSACTION_PARAMS_KEY: convert.bytes_to_hex(eth_fixtures.ACL_TRANSACTION), rpc_constants.STATUS_TRACK_PARAMS_KEY: "True" })) self.assertEqual("1", result.id) self.assertIsNone(result.error) self.assertEqual(eth_fixtures.ACL_TRANSACTION_HASH, result.result["tx_hash"]) self.assertEqual(2, len(self.gateway_node.broadcast_messages)) self.assertEqual( Sha256Hash(convert.hex_to_bytes( eth_fixtures.ACL_TRANSACTION_HASH)), self.gateway_node.broadcast_messages[1][0].tx_hash())
def get_segwit_block(): root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) with open(os.path.join(root_dir, "samples/btc_segwit_sample_block.txt")) as sample_file: btc_block = sample_file.read().strip("\n") block = convert.hex_to_bytes(btc_block) buf = bytearray(BTC_HDR_COMMON_OFF + len(block)) buf[BTC_HDR_COMMON_OFF:] = block msg = BtcMessage(magic="main", command=BlockBtcMessage.MESSAGE_TYPE, payload_len=len(block), buf=buf) parsed_block = BlockBtcMessage(buf=msg.buf) return parsed_block
def clean_block_transactions( self, block_msg: BlockBtcMessage, transaction_service: TransactionService ) -> None: start_datetime = datetime.utcnow() start_time = time.time() tx_hash_to_contents_len_before_cleanup = transaction_service.get_tx_hash_to_contents_len() cleanup_task = self.block_cleanup_tasks.borrow_task() tx_service = typing.cast(ExtensionTransactionService, transaction_service) cleanup_task.init(tpe.InputBytes(block_msg.buf), tx_service.proxy) init_time = time.time() task_pool_proxy.run_task(cleanup_task) task_run_time = time.time() unknown_tx_hashes_count = len(cleanup_task.unknown_tx_hashes()) tx_property_fetch_time = time.time() short_ids = cleanup_task.short_ids() short_ids_fetch_time = time.time() short_ids_count = len(short_ids) tx_service.update_removed_transactions(cleanup_task.total_content_removed(), short_ids) remove_from_tx_service_time = time.time() # TODO : clean the short ids/transactions from the alarm queue after refactoring the transaction service block_hash = block_msg.block_hash() tx_service.on_block_cleaned_up(block_hash) tx_hash_to_contents_len_after_cleanup = transaction_service.get_tx_hash_to_contents_len() end_datetime = datetime.utcnow() end_time = time.time() logger.statistics( { "type": "BlockTransactionsCleanup", "block_hash": repr(block_hash), "unknown_tx_hashes_count": unknown_tx_hashes_count, "short_ids_count": short_ids_count, "block_transactions_count": cleanup_task.txn_count(), "start_datetime": start_datetime, "end_datetime": end_datetime, "task_init_time": init_time - start_time, "task_run_time": task_run_time - init_time, "tx_property_fetch_time": tx_property_fetch_time - task_run_time, "short_ids_fetch_time": short_ids_fetch_time - tx_property_fetch_time, "remove_from_tx_service_time": remove_from_tx_service_time - short_ids_fetch_time, "duration": end_time - start_time, "tx_hash_to_contents_len_before_cleanup": tx_hash_to_contents_len_before_cleanup, "tx_hash_to_contents_len_after_cleanup": tx_hash_to_contents_len_after_cleanup, } ) self.block_cleanup_tasks.return_task(cleanup_task) self._block_hash_marked_for_cleanup.discard(block_hash) self.node.post_block_cleanup_tasks( block_hash=block_hash, short_ids=short_ids, unknown_tx_hashes=( Sha256Hash(convert.hex_to_bytes(tx_hash.hex_string())) for tx_hash in cleanup_task.unknown_tx_hashes() ) )
def from_json(cls, payload: Dict[str, Any]) -> "Transaction": return AccessListTransaction( int(payload["chainId"], 16), int(payload["nonce"], 16), int(payload["gasPrice"], 16), int(payload["gas"], 16), utils.or_else( utils.optional_map(payload["to"], lambda to: convert.hex_to_bytes(to[2:])), bytes()), int(payload["value"], 16), convert.hex_to_bytes(payload["input"][2:]), [ AccessedAddress.from_json(accessed_address) for accessed_address in payload["accessList"] ], int(payload["v"], 16), int(payload["r"], 16), int(payload["s"], 16), )
def test_from_json(self): result = Transaction.from_json(SAMPLE_TRANSACTION_FROM_WS) self.assertEqual(488, result.nonce) self.assertEqual(17679998398, result.gas_price) self.assertEqual(39866, result.start_gas) self.assertEqual(convert.hex_to_bytes(SAMPLE_TRANSACTION["to"][2:]), result.to) self.assertEqual(0, result.value) self.assertEqual(convert.hex_to_bytes(SAMPLE_TRANSACTION["input"][2:]), result.data) self.assertEqual(int(SAMPLE_TRANSACTION["v"], 16), result.v) self.assertEqual(int(SAMPLE_TRANSACTION["r"], 16), result.r) self.assertEqual(int(SAMPLE_TRANSACTION["s"], 16), result.s) result_json = result.to_json() for key, val in SAMPLE_TRANSACTION_FROM_WS.items(): # camelcase problems if key == "gasPrice": key = "gas_price" self.assertEqual(val, result_json[key])
def validate_pub_key(key) -> None: if key.startswith("0x"): key = key[2:] if len(key) != 2 * eth_common_constants.PUBLIC_KEY_LEN: logger.fatal(log_messages.INVALID_PUBLIC_KEY_LENGTH, len(key), exc_info=False) sys.exit(1) eccx_obj = ECCx() if not eccx_obj.is_valid_key(hex_to_bytes(key)): logger.fatal(log_messages.INVALID_PUBLIC_KEY, exc_info=False) sys.exit(1)
def test_plain_compression(self): parsed_block = get_sample_block() bx_block, bx_block_info = self.ont_message_converter.block_to_bx_block( parsed_block, self.tx_service, True, 0) ref_block, block_info, _, _ = self.ont_message_converter.bx_block_to_block( bx_block, self.tx_service) self.assertEqual(parsed_block.rawbytes().tobytes(), ref_block.rawbytes().tobytes()) self.assertEqual(self.SAMPLE_BLOCK_TX_COUNT, parsed_block.txn_count()) self.assertEqual(self.SAMPLE_BLOCK_TX_COUNT, ref_block.txn_count()) self.assertEqual( bytearray(convert.hex_to_bytes(self.SAMPLE_BLOCK_PREV_BLOCK_HASH)), parsed_block.prev_block_hash().get_little_endian()) self.assertEqual( bytearray(convert.hex_to_bytes(self.SAMPLE_BLOCK_PREV_BLOCK_HASH)), ref_block.prev_block_hash().get_little_endian()) self.assertEqual( bytearray(convert.hex_to_bytes(self.SAMPLE_BLOCK_BLOCK_HASH)), parsed_block.block_hash().get_little_endian()) self.assertEqual( bytearray(convert.hex_to_bytes(self.SAMPLE_BLOCK_BLOCK_HASH)), ref_block.block_hash().get_little_endian())
async def handle_block_notifications(self, subscription_id: str) -> None: while self.running: next_notification = await self.get_next_subscription_notification_by_id( subscription_id) logger.debug("NewBlockHeader Notification {} from node", next_notification) block_header = next_notification.notification block_hash = Sha256Hash( convert.hex_to_bytes(block_header["hash"][2:])) block_number = int(block_header["number"], 16) self.node.publish_block(block_number, block_hash, None, FeedSource.BLOCKCHAIN_RPC)
def get_node_public_key(self, ip: str, port: int) -> bytes: node_public_key = None for blockchain_peer in self.blockchain_peers: if blockchain_peer.ip == ip and blockchain_peer.port == port: node_public_key = blockchain_peer.node_public_key break if not node_public_key: raise RuntimeError( f"128 digit public key must be included with for blockchain peer ip {ip} and port {port}." ) return convert.hex_to_bytes(node_public_key)
def __init__(self, opts, node_ssl_service: NodeSSLService): super(EthGatewayNode, self).__init__(opts, node_ssl_service, eth_common_constants.TRACKED_BLOCK_CLEANUP_INTERVAL_S) self._node_public_key = None self._remote_public_key = None if opts.node_public_key is not None: self._node_public_key = convert.hex_to_bytes(opts.node_public_key) else: raise RuntimeError( "128 digit public key must be included with command-line specified blockchain peer.") if opts.remote_blockchain_peer is not None: if opts.remote_public_key is None: raise RuntimeError( "128 digit public key must be included with command-line specified remote blockchain peer.") else: self._remote_public_key = convert.hex_to_bytes(opts.remote_public_key) self.block_processing_service: EthBlockProcessingService = EthBlockProcessingService(self) self.block_queuing_service: EthBlockQueuingService = EthBlockQueuingService(self) # List of know total difficulties, tuples of values (block hash, total difficulty) self._last_known_difficulties = deque(maxlen=eth_common_constants.LAST_KNOWN_TOTAL_DIFFICULTIES_MAX_COUNT) # queue of the block hashes requested from remote blockchain node during sync self._requested_remote_blocks_queue = deque() # number of remote block requests to skip in case if requests and responses got out of sync self._skip_remote_block_requests_stats_count = 0 self.init_eth_gateway_stat_logging() self.message_converter = converter_factory.create_eth_message_converter(self.opts) self.eth_ws_subscriber = EthWsSubscriber(opts.eth_ws_uri, self.feed_manager, self._tx_service) if self.opts.ws and not self.opts.eth_ws_uri: logger.warning(log_messages.ETH_WS_SUBSCRIBER_NOT_STARTED) logger.info("Gateway enode url: {}", self.get_enode())
def get_dummy_transaction(nonce: int, gas_price: Optional[int] = None, v: int = 27, to_address_str: Optional[str] = None) -> Transaction: if gas_price is None: gas_price = 2 * nonce if to_address_str is None: to_address = helpers.generate_bytes(eth_common_constants.ADDRESS_LEN) else: to_address = convert.hex_to_bytes(to_address_str) # create transaction object with dummy values multiplied by nonce to be able generate txs with different values return Transaction(nonce, gas_price, 3 * nonce, to_address, 4 * nonce, helpers.generate_bytes(15 * nonce), v, 6 * nonce, 7 * nonce)
async def test_blxr_tx(self): result = await self.request( BxJsonRpcRequest( "1", RpcRequestType.BLXR_TX, { rpc_constants.TRANSACTION_PARAMS_KEY: RAW_TRANSACTION_HEX, rpc_constants.STATUS_TRACK_PARAMS_KEY: "True" })) self.assertEqual("1", result.id) self.assertIsNone(result.error) self.assertEqual(TRANSACTION_HASH, result.result["tx_hash"]) self.assertEqual(1, len(self.gateway_node.broadcast_messages)) self.assertEqual(Sha256Hash(convert.hex_to_bytes(TRANSACTION_HASH)), self.gateway_node.broadcast_messages[0][0].tx_hash())
def _enqueue_status_message(self, chain_difficulty: int, fork_id): network_id = self.node.opts.network_id chain_head_hash = convert.hex_to_bytes(self.node.opts.genesis_hash) genesis_hash = convert.hex_to_bytes(self.node.opts.genesis_hash) eth_protocol_version = self._get_eth_protocol_version() if eth_common_constants.ETH_PROTOCOL_VERSION == gateway_constants.ETH_PROTOCOL_VERSION_63: status_msg = StatusEthProtocolMessageV63( None, eth_protocol_version, network_id, chain_difficulty, chain_head_hash, genesis_hash, ) else: status_msg = StatusEthProtocolMessage(None, eth_protocol_version, network_id, chain_difficulty, chain_head_hash, genesis_hash, fork_id) self.connection.enqueue_msg(status_msg) self.connection_status.status_message_sent = True