split cache_block and to_block

This commit is contained in:
Bryan Stitt 2023-10-31 19:04:20 -07:00
parent 6e891d9081
commit 51594cb1c0
2 changed files with 53 additions and 33 deletions

View File

@ -228,13 +228,21 @@ impl BlockNumOrHash {
} }
} }
impl From<&Web3ProxyBlock> for BlockNumOrHash {
fn from(value: &Web3ProxyBlock) -> Self {
Self::And(value.into())
}
}
/// TODO: change this to also return the hash needed? /// TODO: change this to also return the hash needed?
/// this replaces any "latest" identifiers in the JsonRpcRequest with the current block number which feels like the data is structured wrong /// this replaces any "latest" identifiers in the JsonRpcRequest with the current block number which feels like the data is structured wrong
#[derive(Debug, Default, Hash, Eq, PartialEq)] #[derive(Debug, Default, Hash, Eq, PartialEq)]
pub enum CacheMode { pub enum CacheMode {
SuccessForever, SuccessForever,
Standard { Standard {
block: BlockNumAndHash, /// TODO: i don't think i'm using this correctly everywhere. i think we return an error if this can't be found when we should just allow the number
block_needed: BlockNumOrHash,
cache_block: BlockNumAndHash,
/// cache jsonrpc errors (server errors are never cached) /// cache jsonrpc errors (server errors are never cached)
cache_errors: bool, cache_errors: bool,
}, },
@ -305,7 +313,8 @@ impl CacheMode {
if let Some(head_block) = head_block { if let Some(head_block) = head_block {
Self::Standard { Self::Standard {
block: head_block.into(), block_needed: head_block.into(),
cache_block: head_block.into(),
cache_errors: true, cache_errors: true,
} }
} else { } else {
@ -320,18 +329,6 @@ impl CacheMode {
) -> Web3ProxyResult<Self> { ) -> Web3ProxyResult<Self> {
let params = &mut request.params; let params = &mut request.params;
if matches!(params, serde_json::Value::Null) {
// no params given. cache with the head block
if let Some(head_block) = head_block {
return Ok(Self::Standard {
block: head_block.into(),
cache_errors: true,
});
} else {
return Ok(Self::Never);
}
}
if head_block.is_none() { if head_block.is_none() {
// since we don't have a head block, i don't trust our anything enough to cache // since we don't have a head block, i don't trust our anything enough to cache
return Ok(Self::Never); return Ok(Self::Never);
@ -339,11 +336,21 @@ impl CacheMode {
let head_block = head_block.expect("head_block was just checked above"); let head_block = head_block.expect("head_block was just checked above");
if matches!(params, serde_json::Value::Null) {
// no params given. cache with the head block
return Ok(Self::Standard {
block_needed: head_block.into(),
cache_block: head_block.into(),
cache_errors: true,
});
}
if let Some(params) = params.as_array() { if let Some(params) = params.as_array() {
if params.is_empty() { if params.is_empty() {
// no params given. cache with the head block // no params given. cache with the head block
return Ok(Self::Standard { return Ok(Self::Standard {
block: head_block.into(), block_needed: head_block.into(),
cache_block: head_block.into(),
cache_errors: true, cache_errors: true,
}); });
} }
@ -354,10 +361,7 @@ impl CacheMode {
// TODO: make sure re-orgs work properly! // TODO: make sure re-orgs work properly!
Ok(Self::SuccessForever) Ok(Self::SuccessForever)
} }
"eth_gasPrice" => Ok(Self::Standard { "eth_gasPrice" => Ok(Self::Never),
block: head_block.into(),
cache_errors: false,
}),
"eth_getBlockByHash" => { "eth_getBlockByHash" => {
// TODO: double check that any node can serve this // TODO: double check that any node can serve this
// TODO: can a block change? like what if it gets orphaned? // TODO: can a block change? like what if it gets orphaned?
@ -369,7 +373,8 @@ impl CacheMode {
// TODO: CacheSuccessForever if the block is old enough // TODO: CacheSuccessForever if the block is old enough
// TODO: make sure re-orgs work properly! // TODO: make sure re-orgs work properly!
Ok(Self::Standard { Ok(Self::Standard {
block: head_block.into(), block_needed: head_block.into(),
cache_block: head_block.into(),
cache_errors: true, cache_errors: true,
}) })
} }
@ -483,10 +488,7 @@ impl CacheMode {
} }
"eth_maxPriorityFeePerGas" => { "eth_maxPriorityFeePerGas" => {
// TODO: this might be too aggressive. i think it can change before a block is mined // TODO: this might be too aggressive. i think it can change before a block is mined
Ok(Self::Standard { Ok(Self::Never)
block: head_block.into(),
cache_errors: false,
})
} }
"eth_sendRawTransaction" => Ok(Self::Never), "eth_sendRawTransaction" => Ok(Self::Never),
"net_listening" => Ok(Self::SuccessForever), "net_listening" => Ok(Self::SuccessForever),
@ -496,7 +498,8 @@ impl CacheMode {
let block = clean_block_number(params, block_param_id, head_block, app).await?; let block = clean_block_number(params, block_param_id, head_block, app).await?;
Ok(Self::Standard { Ok(Self::Standard {
block, block_needed: BlockNumOrHash::And(block.clone()),
cache_block: block,
cache_errors: true, cache_errors: true,
}) })
} }
@ -530,13 +533,26 @@ impl CacheMode {
!matches!(self, Self::Never) !matches!(self, Self::Never)
} }
/// get the to_block used **for caching**. This may be the to_block in the request, or it might be the current head block.
#[inline] #[inline]
pub fn to_block(&self) -> Option<&BlockNumAndHash> { pub fn to_block(&self) -> Option<&BlockNumOrHash> {
match self { match self {
Self::SuccessForever => None, Self::SuccessForever => None,
Self::Never => None, Self::Never => None,
Self::Standard { block, .. } => Some(block), Self::Standard {
block_needed: block,
..
} => Some(block),
Self::Range { to_block, .. } => Some(to_block),
}
}
/// get the to_block used **for caching**. This may be the to_block in the request, or it might be the current head block.
#[inline]
pub fn cache_block(&self) -> Option<&BlockNumAndHash> {
match self {
Self::SuccessForever => None,
Self::Never => None,
Self::Standard { cache_block, .. } => Some(cache_block),
Self::Range { cache_block, .. } => Some(cache_block), Self::Range { cache_block, .. } => Some(cache_block),
} }
} }
@ -579,7 +595,8 @@ mod test {
assert_eq!( assert_eq!(
x, x,
CacheMode::Standard { CacheMode::Standard {
block: (&head_block).into(), block_needed: (&head_block).into(),
cache_block: (&head_block).into(),
cache_errors: true cache_errors: true
} }
); );
@ -616,7 +633,8 @@ mod test {
assert_eq!( assert_eq!(
x, x,
CacheMode::Standard { CacheMode::Standard {
block: (&head_block).into(), block_needed: (&head_block).into(),
cache_block: (&head_block).into(),
cache_errors: true cache_errors: true
} }
); );

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
block_number::{BlockNumAndHash, BlockNumOrHash, CacheMode}, block_number::{BlockNumOrHash, CacheMode},
errors::{Web3ProxyError, Web3ProxyResult}, errors::{Web3ProxyError, Web3ProxyResult},
frontend::authorization::RequestOrMethod, frontend::authorization::RequestOrMethod,
jsonrpc::{self, JsonRpcErrorData, ResponsePayload}, jsonrpc::{self, JsonRpcErrorData, ResponsePayload},
@ -23,7 +23,7 @@ pub struct JsonRpcQueryCacheKey<'a> {
/// this is probably a premature optimization /// this is probably a premature optimization
hash: u64, hash: u64,
from_block: Option<&'a BlockNumOrHash>, from_block: Option<&'a BlockNumOrHash>,
to_block: Option<&'a BlockNumAndHash>, to_block: Option<&'a BlockNumOrHash>,
cache_jsonrpc_errors: bool, cache_jsonrpc_errors: bool,
} }
@ -64,17 +64,19 @@ impl<'a> JsonRpcQueryCacheKey<'a> {
// TODO: do this without clone // TODO: do this without clone
let from_block = cache_mode.from_block(); let from_block = cache_mode.from_block();
let to_block = cache_mode.to_block(); let to_block = cache_mode.to_block();
let cache_block = cache_mode.cache_block();
let cache_jsonrpc_errors = cache_mode.cache_jsonrpc_errors(); let cache_jsonrpc_errors = cache_mode.cache_jsonrpc_errors();
let mut hasher = DefaultHashBuilder::default().build_hasher(); let mut hasher = DefaultHashBuilder::default().build_hasher();
from_block.hash(&mut hasher); from_block.hash(&mut hasher);
to_block.hash(&mut hasher); to_block.hash(&mut hasher);
cache_block.hash(&mut hasher);
request.method().hash(&mut hasher); request.method().hash(&mut hasher);
// TODO: make sure preserve_order feature is OFF // TODO: make sure preserve_order feature is OFF
// TODO: is there a faster way to do this? // TODO: is there a faster way to do this? can we serialize directly into the hasher?
request.params().to_string().hash(&mut hasher); request.params().to_string().hash(&mut hasher);
cache_jsonrpc_errors.hash(&mut hasher); cache_jsonrpc_errors.hash(&mut hasher);