async def request_missing_bytecode( bytecode_hash: Hash32, block_number: BlockNumber) -> MissingBytecodeResult: if event_bus.is_any_endpoint_subscribed_to(CollectMissingBytecode): return await event_bus.request(CollectMissingBytecode( bytecode_hash, urgent, block_number, )) else: raise StateUnretrievable("No servers for CollectMissingBytecode")
async def request_missing_account( missing_node_hash: Hash32, address_hash: Hash32, state_root_hash: Hash32, block_number: BlockNumber) -> MissingAccountResult: if event_bus.is_any_endpoint_subscribed_to(CollectMissingAccount): return await event_bus.request( CollectMissingAccount( missing_node_hash, address_hash, state_root_hash, urgent, block_number, )) else: raise StateUnretrievable("No servers for CollectMissingAccount")
async def request_missing_storage( missing_node_hash: Hash32, storage_key: Hash32, storage_root_hash: Hash32, account_address: Address, block_number: BlockNumber) -> MissingStorageResult: if event_bus.is_any_endpoint_subscribed_to(CollectMissingStorage): return await event_bus.request( CollectMissingStorage( missing_node_hash, storage_key, storage_root_hash, account_address, urgent, block_number, )) else: raise StateUnretrievable("No servers for CollectMissingStorage")
def _request_missing_data(self, vm_method: Callable[[Any], TVMFuncReturn], *args: Any, **kwargs: Any) -> TVMFuncReturn: """ Catch exceptions about missing state data and pause while waiting for the event bus to reply with the needed data. """ while True: try: return vm_method(*args, **kwargs) # type: ignore except MissingAccountTrieNode as exc: t = Timer() account_future = asyncio.run_coroutine_threadsafe( request_missing_account( exc.missing_node_hash, exc.address_hash, exc.state_root_hash, self.block_number, ), loop, ) account_event = account_future.result( timeout=self.node_retrieval_timeout) if urgent: self.logger.debug( "Paused for account nodes (%d) for %.3fs, %.3fs avg (starts on %s)", account_event.num_nodes_collected, t.elapsed, t.elapsed / (account_event.num_nodes_collected or 1), exc.missing_node_hash[:2].hex(), ) # Collect the amount of paused time before checking if we should exit, so # it shows up in logged statistics. self.stats_counter.data_pause_time += t.elapsed if not account_event.is_retry_acceptable: raise StateUnretrievable( "Server asked us to stop trying") self.stats_counter.num_accounts += 1 self.stats_counter.num_account_nodes += account_event.num_nodes_collected except MissingBytecode as exc: t = Timer() bytecode_future = asyncio.run_coroutine_threadsafe( request_missing_bytecode( exc.missing_code_hash, self.block_number, ), loop, ) bytecode_event = bytecode_future.result( timeout=self.node_retrieval_timeout) if urgent: self.logger.debug( "Paused for bytecode for %.3fs (%s)", t.elapsed, exc.missing_code_hash[:2].hex(), ) self.stats_counter.data_pause_time += t.elapsed if not bytecode_event.is_retry_acceptable: raise StateUnretrievable( "Server asked us to stop trying") self.stats_counter.num_bytecodes += 1 except MissingStorageTrieNode as exc: t = Timer() storage_future = asyncio.run_coroutine_threadsafe( request_missing_storage( exc.missing_node_hash, exc.requested_key, exc.storage_root_hash, exc.account_address, self.block_number, ), loop, ) storage_event = storage_future.result( timeout=self.node_retrieval_timeout) if urgent: self.logger.debug( "Paused for storage nodes (%d) for %.3fs, %.3fs avg (starts on %s)", storage_event.num_nodes_collected, t.elapsed, t.elapsed / (storage_event.num_nodes_collected or 1), exc.missing_node_hash[:2].hex(), ) self.stats_counter.data_pause_time += t.elapsed if not storage_event.is_retry_acceptable: raise StateUnretrievable( "Server asked us to stop trying") self.stats_counter.num_storages += 1 self.stats_counter.num_storage_nodes += storage_event.num_nodes_collected