diff --git a/src/dexorder/blockchain/connection.py b/src/dexorder/blockchain/connection.py index caba6e0..77122b5 100644 --- a/src/dexorder/blockchain/connection.py +++ b/src/dexorder/blockchain/connection.py @@ -181,30 +181,29 @@ ARCHIVE_ERRORS = { 'state recreation l2 gas depth limit exceeded', } + +def is_archive_method(method, params): + expected_args = ARCHIVE_METHODS.get(method, -1) + return len(params) == expected_args + + async def archive_intercept_middleware(make_request, w3): """ Middleware to intercept any call with `block_number` and manage marking archive_fault_height """ async def middleware(method, params): # Only intercept relevant methods - expected_args = ARCHIVE_METHODS.get(method,-1) - is_archive_method = len(params) == expected_args + is_archival = is_archive_method(method, params) block_height = None - if is_archive_method: + resp = await make_request(method, params) + if is_archival and 'error' in resp and resp['error']['message'] in ARCHIVE_ERRORS: block_identifier = params[-1] if block_identifier not in ('latest', 'pending',): block_height = int(block_identifier, 16) if type(block_identifier) is str else int(params[-1]) - if block_height <= w3.archive_fault_height: - # this block is at least as old as another block that already failed to fetch history from this RPC - raise ArchiveException(method, block_height) - resp = await make_request(method, params) - if is_archive_method and 'error' in resp and resp['error']['message'] in ARCHIVE_ERRORS: - if block_height is None: + raise ArchiveException(method, block_height) + else: # noinspection PyUnboundLocalVariable raise Exception(f'Got an archive fault using a block_identifier of {block_identifier}: {w3.provider.endpoint_uri} {method} {params}\n{resp}') - # noinspection PyTypeChecker - w3.archive_fault_height = max(w3.archive_fault_height, block_height) - raise ArchiveException(method, block_height) return resp return middleware @@ -287,7 +286,15 @@ class RoundRobinHTTPProvider (AsyncJSONBaseProvider): async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: provider = self._current() + is_archival = is_archive_method(method, params) try: + if is_archival: + block_identifier = params[-1] + if block_identifier not in ('latest', 'pending',): + block_height = int(block_identifier, 16) if type(block_identifier) is str else int(params[-1]) + if block_height <= provider.archive_fault_height: + # this block is at least as old as another block that already failed to fetch history from this RPC + raise ArchiveException(method, block_height) return await provider.make_request(method, params) except ArchiveException as e: provider.archive_fault_height = max(provider.archive_fault_height, e.block_number)