diff --git a/web3_proxy/src/rpcs/blockchain.rs b/web3_proxy/src/rpcs/blockchain.rs index b2bd521c..12bba91a 100644 --- a/web3_proxy/src/rpcs/blockchain.rs +++ b/web3_proxy/src/rpcs/blockchain.rs @@ -1,9 +1,8 @@ //! Keep track of the blockchain as seen by a Web3Rpcs. use super::consensus::ConsensusFinder; use super::many::Web3Rpcs; -use super::one::Web3Rpc; use crate::config::{average_block_interval, BlockAndRpc}; -use crate::errors::{Web3ProxyError, Web3ProxyErrorContext, Web3ProxyResult}; +use crate::errors::{Web3ProxyError, Web3ProxyResult}; use ethers::prelude::{Block, TxHash, H256, U64}; use moka::future::Cache; use serde::ser::SerializeStruct; @@ -187,160 +186,6 @@ impl Web3Rpcs { Ok(block) } - /// Get a block from caches with fallback. - /// Will query a specific node or the best available. - pub async fn block( - &self, - hash: &H256, - rpc: Option<&Arc>, - max_wait: Option, - ) -> Web3ProxyResult { - // first, try to get the hash from our cache - // the cache is set last, so if its here, its everywhere - // TODO: use try_get_with - if let Some(block) = self.blocks_by_hash.get(hash).await { - // double check that it matches the blocks_by_number cache - let cached_hash = self - .blocks_by_number - .get_with(block.number(), async { *hash }) - .await; - - if cached_hash == *hash { - return Ok(block); - } - - // hashes don't match! this block must be in the middle of being uncled - // TODO: check known uncles. clear uncle caches - } - - if hash == &H256::zero() { - // TODO: think more about this - return Err(Web3ProxyError::UnknownBlockHash(*hash)); - } - - // block not in cache. we need to ask an rpc for it - let get_block_params = (*hash, false); - - let mut block: Option = if let Some(rpc) = rpc { - // ask a specific rpc - // if this errors, other rpcs will be tried - rpc.internal_request::<_, Option>( - "eth_getBlockByHash", - &get_block_params, - None, - max_wait, - ) - .await - .ok() - .flatten() - } else { - None - }; - - if block.is_none() { - // try by asking any rpc - // TODO: retry if "Requested data is not available" - // TODO: request_with_metadata instead of internal_request - block = self - .internal_request::<_, Option>( - "eth_getBlockByHash", - &get_block_params, - max_wait, - ) - .await?; - }; - - match block { - Some(block) => { - let block = self - .try_cache_block( - Web3ProxyBlock::try_new(block) - .ok_or(Web3ProxyError::UnknownBlockHash(*hash))?, - false, - ) - .await?; - Ok(block) - } - None => Err(Web3ProxyError::UnknownBlockHash(*hash)), - } - } - - /// Convenience method to get the cannonical block at a given block height. - pub async fn block_hash(&self, num: &U64) -> Web3ProxyResult { - let block = self.cannonical_block(num).await?; - - let hash = *block.hash(); - - Ok(hash) - } - - /// Get the heaviest chain's block from cache or backend rpc - /// Caution! If a future block is requested, this might wait forever. Be sure to have a timeout outside of this! - pub async fn cannonical_block(&self, num: &U64) -> Web3ProxyResult { - // we only have blocks by hash now - // maybe save them during save_block in a blocks_by_number Cache> - // TODO: if theres multiple, use petgraph to find the one on the main chain (and remove the others if they have enough confirmations) - - // try to get the hash from our cache - if let Some(block_hash) = self.blocks_by_number.get(num).await { - // TODO: sometimes this needs to fetch the block. why? i thought block_numbers would only be set if the block hash was set - // TODO: configurable max wait and rpc - return self.block(&block_hash, None, None).await; - } - - let mut consensus_head_receiver = self - .watch_head_block - .as_ref() - .web3_context("need new head subscriptions to fetch cannonical_block")? - .subscribe(); - - // be sure the requested block num exists - // TODO: is this okay? what if we aren't synced?! - let mut head_block_num = consensus_head_receiver - .borrow_and_update() - .as_ref() - .web3_context("no consensus head block")? - .number(); - - if *num > head_block_num { - // if num is too far in the future, error now - if *num - head_block_num > self.max_head_block_lag { - return Err(Web3ProxyError::UnknownBlockNumber { - known: head_block_num, - unknown: *num, - }); - } - - while *num > head_block_num { - debug!(%head_block_num, %num, "waiting for future block"); - - consensus_head_receiver.changed().await?; - - if let Some(head) = consensus_head_receiver.borrow_and_update().as_ref() { - head_block_num = head.number(); - } - } - } - - // block number not in cache. we need to ask an rpc for it - // TODO: this error is too broad - let response = self - .internal_request::<_, Option>("eth_getBlockByNumber", &(*num, false), None) - .await? - .ok_or(Web3ProxyError::NoBlocksKnown)?; - - let block = - Web3ProxyBlock::try_new(response).ok_or(Web3ProxyError::UnknownBlockNumber { - known: head_block_num, - unknown: *num, - })?; - - // the block was fetched using eth_getBlockByNumber, so it should have all fields and be on the heaviest chain - let block = self.try_cache_block(block, true).await?; - - Ok(block) - } - pub(super) async fn process_incoming_blocks( &self, mut block_and_rpc_receiver: mpsc::UnboundedReceiver,