async def request_missing_account( missing_node_hash: Hash32, address_hash: Hash32, state_root_hash: Hash32) -> MissingAccountCollected: return await event_bus.request(CollectMissingAccount( missing_node_hash, address_hash, state_root_hash, ))
async def _hang_until_account_served(self, event: CollectMissingAccount) -> None: try: await self.wait(self._serve_account(event)) except OperationCancelled: # Beam sync is shutting down, probably either because the node is closing, or # a pivot is required. So communicate that import should stop. await self._event_bus.broadcast( MissingAccountResult(is_retry_acceptable=False), event.broadcast_config(), ) raise
async def _serve_account(self, event: CollectMissingAccount) -> None: await self._state_downloader.ensure_node_present( event.missing_node_hash) _, num_nodes_collected = await self._state_downloader.download_account( event.address_hash, event.state_root_hash, ) await self._event_bus.broadcast( MissingAccountCollected(num_nodes_collected), event.broadcast_config(), )
async def _serve_account(self, event: CollectMissingAccount) -> None: _, num_nodes_collected = await self._state_downloader.download_account( event.address_hash, event.state_root_hash, event.urgent, ) bonus_node = await self._state_downloader.ensure_nodes_present( {event.missing_node_hash}, event.urgent, ) await self._event_bus.broadcast( MissingAccountResult(num_nodes_collected + bonus_node), event.broadcast_config(), )
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 _hang_until_account_served(self, event: CollectMissingAccount) -> None: try: await asyncio.wait_for( self._serve_account(event), timeout=BLOCK_IMPORT_MISSING_STATE_TIMEOUT, ) except asyncio.CancelledError: # Beam sync is shutting down, probably either because the node is closing, or # a pivot is required. So communicate that import should stop. await self._event_bus.broadcast( MissingAccountResult(is_retry_acceptable=False), event.broadcast_config(), ) raise except asyncio.TimeoutError: pass
async def execute_with_retries( event_bus: EndpointAPI, func: Func, params: Any, chain: Union[AsyncChainAPI, BaseAsyncBeaconChainDB]) -> None: """ If a beam sync (or anything which responds to CollectMissingAccount) is running then attempt to fetch missing data from it before giving up. """ retryable = is_retryable(func) for iteration in itertools.count(): try: return await func(*params) except MissingAccountTrieNode as exc: if not retryable: raise if iteration > MAX_RETRIES: raise Exception( f"Failed to collect all necessary state after {MAX_RETRIES} attempts" ) from exc if not event_bus.is_any_endpoint_subscribed_to( CollectMissingAccount): raise requested_header = await check_requested_block_age( chain, func, params) await event_bus.request( CollectMissingAccount( exc.missing_node_hash, exc.address_hash, exc.state_root_hash, urgent=True, block_number=requested_header.block_number, )) except MissingBytecode as exc: if not retryable: raise if iteration > MAX_RETRIES: raise Exception( f"Failed to collect all necessary state after {MAX_RETRIES} attempts" ) from exc if not event_bus.is_any_endpoint_subscribed_to( CollectMissingBytecode): raise requested_header = await check_requested_block_age( chain, func, params) await event_bus.request( CollectMissingBytecode( bytecode_hash=exc.missing_code_hash, urgent=True, block_number=requested_header.block_number, )) except MissingStorageTrieNode as exc: if not retryable: raise if iteration > MAX_RETRIES: raise Exception( f"Failed to collect all necessary state after {MAX_RETRIES} attempts" ) from exc if not event_bus.is_any_endpoint_subscribed_to( CollectMissingStorage): raise requested_header = await check_requested_block_age( chain, func, params) await event_bus.request( CollectMissingStorage( missing_node_hash=exc.missing_node_hash, storage_key=exc.requested_key, storage_root_hash=exc.storage_root_hash, account_address=exc.account_address, urgent=True, block_number=requested_header.block_number, ))
async def collect_accounts(event: CollectMissingAccount): replace_missing_node(event.missing_node_hash) await event_bus.broadcast( MissingAccountResult(1), event.broadcast_config() )