diff --git a/fluffy/network/history/history_network.nim b/fluffy/network/history/history_network.nim index f42be6f13..b16c66981 100644 --- a/fluffy/network/history/history_network.nim +++ b/fluffy/network/history/history_network.nim @@ -176,7 +176,7 @@ proc validateBlockBodyBytes*( try: SSZ.decode(bytes, BlockBodySSZ) except SszError as e: - return err("Failed to decode block body" & e.msg) + return err("Failed to decode block body: " & e.msg) ? validateBlockBody(body, txRoot, ommersHash) @@ -199,7 +199,7 @@ proc validateReceiptsBytes*( try: SSZ.decode(bytes, ReceiptsSSZ) except SszError as e: - return err("Failed to decode receipts" & e.msg) + return err("Failed to decode receipts: " & e.msg) ? validateReceipts(receipts, receiptsRoot) @@ -262,6 +262,15 @@ proc getContentFromDb( ## Public API to get the history network specific types, either from database ## or through a lookup on the Portal Network +const requestRetries = 4 +# TODO: Currently doing 4 retries on lookups but only when the validation fails. +# This is to avoid nodes that provide garbage from blocking us with getting the +# requested data. Might want to also do that on a failed lookup, as perhaps this +# could occur when being really unlucky with nodes timing out on requests. +# Additionally, more improvements could be done with the lookup, as currently +# ongoing requests are cancelled after the receival of the first response, +# however that response is not yet validated at that moment. + proc getBlockHeader*( h: HistoryNetwork, chainId: uint16, hash: BlockHash): Future[Option[BlockHeader]] {.async.} = @@ -273,71 +282,72 @@ proc getBlockHeader*( info "Fetched block header from database", hash return headerFromDb - let headerContentLookup = - await h.portalProtocol.contentLookup(keyEncoded, contentId) - if headerContentLookup.isNone(): - warn "Failed fetching block header from the network", hash - return none(BlockHeader) + for i in 0.. Option[ReceiptObject]: - rpcServerWithProxy.rpc("eth_getLogs") do(filterOptions: FilterOptions) -> seq[FilterLog]: + rpcServerWithProxy.rpc("eth_getLogs") do( + filterOptions: FilterOptions) -> seq[FilterLog]: if filterOptions.blockhash.isNone(): - # currently only queries with provided blockhash are supported. To support - # range queries it would require Indicies network. - raise newException(ValueError, "Unsupported query. Field `blockhash` needs to be provided") + # Currently only queries by blockhash are supported. + # To support range queries the Indicies network is required. + raise newException(ValueError, + "Unsupported query: Only `blockhash` queries are currently supported") else: let hash = filterOptions.blockHash.unsafeGet() - let maybeHeader = await historyNetwork.getBlockHeader(1'u16, hash) + let headerOpt = await historyNetwork.getBlockHeader(1'u16, hash) + if headerOpt.isNone(): + raise newException(ValueError, + "Could not find header with requested hash") - if maybeHeader.isNone(): - raise newException(ValueError, "Could not find header with requested hash") - - let header = maybeHeader.unsafeGet() + let header = headerOpt.unsafeGet() if headerBloomFilter(header, filterOptions.address, filterOptions.topics): # TODO: These queries could be done concurrently, investigate if there # are no assumptions about usage of concurrent queries on portal # wire protocol level - let maybeBody = await historyNetwork.getBlockBody(1'u16, hash, header) - let maybeReceipts = await historyNetwork.getReceipts(1'u16, hash, header) + let + bodyOpt = await historyNetwork.getBlockBody(1'u16, hash, header) + receiptsOpt = await historyNetwork.getReceipts(1'u16, hash, header) + + if bodyOpt.isSome() and receiptsOpt.isSome(): + let + body = bodyOpt.unsafeGet() + receipts = receiptsOpt.unsafeGet() + logs = deriveLogs(header, body.transactions, receipts) + filteredLogs = filterLogs( + logs, filterOptions.address, filterOptions.topics) - if maybeBody.isSome() and maybeReceipts.isSome(): - let body = maybeBody.unsafeGet() - let receipts = maybeReceipts.unsafeGet() - let logs = deriveLogs(header, body.transactions, receipts) - let filteredLogs = filterLogs(logs, filterOptions.address, filterOptions.topics) return filteredLogs else: - if maybeBody.isNone(): - raise newException(ValueError, "Could not find body for requested hash") + if bodyOpt.isNone(): + raise newException(ValueError, + "Could not find block body for requested hash") else: - raise newException(ValueError, "Could not find receipts for requested hash") + raise newException(ValueError, + "Could not find receipts for requested hash") else: - # bloomfilter returned false, we do known that there is no logs matching - # given criteria + # bloomfilter returned false, we do known that there are no logs + # matching the given criteria return @[]