From bf13e86a0414d72271aa50999ab07f8e4f054850 Mon Sep 17 00:00:00 2001 From: Bryan Stitt Date: Sat, 17 Jun 2023 09:19:05 -0700 Subject: [PATCH] warn if no max_head_block_age --- config/development_polygon.toml | 2 ++ config/example.toml | 3 +++ web3_proxy/src/app/mod.rs | 10 +++++++--- web3_proxy/src/config.rs | 2 +- web3_proxy/src/rpcs/blockchain.rs | 3 ++- web3_proxy/src/rpcs/consensus.rs | 9 +++++---- web3_proxy/src/rpcs/many.rs | 14 +++++++------- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/config/development_polygon.toml b/config/development_polygon.toml index 5f6d80e7..cbae4186 100644 --- a/config/development_polygon.toml +++ b/config/development_polygon.toml @@ -23,6 +23,8 @@ min_sum_soft_limit = 1_000 # only mark a block as the head block if the number of servers with it is great than or equal to min_synced_rpcs min_synced_rpcs = 1 +max_head_block_age = 30 + # redis is optional. it is used for rate limits set by `hard_limit` # TODO: how do we find the optimal redis_max_connections? too high actually ends up being slower volatile_redis_max_connections = 20 diff --git a/config/example.toml b/config/example.toml index 6c6673d1..28a4ba96 100644 --- a/config/example.toml +++ b/config/example.toml @@ -28,6 +28,9 @@ min_sum_soft_limit = 2_000 # only mark a block as the head block if the number of servers with it is great than or equal to min_synced_rpcs min_synced_rpcs = 2 +# don't serve requests if the best known block is >60 seconds old +max_head_block_age = 60 + # redis is optional. it is used for rate limits set by `hard_limit` # TODO: how do we find the optimal redis_max_connections? too high actually ends up being slower volatile_redis_max_connections = 300 diff --git a/web3_proxy/src/app/mod.rs b/web3_proxy/src/app/mod.rs index 7c5ae9c6..a8b4225b 100644 --- a/web3_proxy/src/app/mod.rs +++ b/web3_proxy/src/app/mod.rs @@ -196,6 +196,10 @@ impl Web3ProxyApp { ); } + if top_config.app.max_head_block_age.is_none() { + warn!("no max_head_block_age. stale data could be served!"); + } + if !top_config.extra.is_empty() { warn!( "unknown TopConfig fields!: {:?}", @@ -501,7 +505,7 @@ impl Web3ProxyApp { let (balanced_rpcs, balanced_handle, consensus_connections_watcher) = Web3Rpcs::spawn( db_conn.clone(), - top_config.app.max_block_age, + top_config.app.max_head_block_age, top_config.app.max_block_lag, top_config.app.min_synced_rpcs, top_config.app.min_sum_soft_limit, @@ -526,7 +530,7 @@ impl Web3ProxyApp { // let (private_rpcs, private_rpcs_handle) = Web3Rpcs::spawn( let (private_rpcs, private_handle, _) = Web3Rpcs::spawn( db_conn.clone(), - // private rpcs don't get subscriptions, so no need for max_block_age or max_block_lag + // private rpcs don't get subscriptions, so no need for max_head_block_age or max_block_lag None, None, 0, @@ -558,7 +562,7 @@ impl Web3ProxyApp { // TODO: do something with the spawn handle let (bundler_4337_rpcs, bundler_4337_rpcs_handle, _) = Web3Rpcs::spawn( db_conn.clone(), - // bundler_4337_rpcs don't get subscriptions, so no need for max_block_age or max_block_lag + // bundler_4337_rpcs don't get subscriptions, so no need for max_head_block_age or max_block_lag None, None, 0, diff --git a/web3_proxy/src/config.rs b/web3_proxy/src/config.rs index a6315fb1..80d86aa6 100644 --- a/web3_proxy/src/config.rs +++ b/web3_proxy/src/config.rs @@ -121,7 +121,7 @@ pub struct AppConfig { pub login_domain: Option, /// do not serve any requests if the best known block is older than this many seconds. - pub max_block_age: Option, + pub max_head_block_age: Option, /// do not serve any requests if the best known block is behind the best known block by more than this many blocks. pub max_block_lag: Option, diff --git a/web3_proxy/src/rpcs/blockchain.rs b/web3_proxy/src/rpcs/blockchain.rs index 8913808b..b6de5ebd 100644 --- a/web3_proxy/src/rpcs/blockchain.rs +++ b/web3_proxy/src/rpcs/blockchain.rs @@ -401,7 +401,8 @@ impl Web3Rpcs { // Geth's subscriptions have the same potential for skipping blocks. pending_tx_sender: Option>, ) -> Web3ProxyResult<()> { - let mut connection_heads = ConsensusFinder::new(self.max_block_age, self.max_block_lag); + let mut connection_heads = + ConsensusFinder::new(self.max_head_block_age, self.max_block_lag); loop { match block_receiver.recv_async().await { diff --git a/web3_proxy/src/rpcs/consensus.rs b/web3_proxy/src/rpcs/consensus.rs index 9808b196..1890b33c 100644 --- a/web3_proxy/src/rpcs/consensus.rs +++ b/web3_proxy/src/rpcs/consensus.rs @@ -339,7 +339,7 @@ type FirstSeenCache = Cache; pub struct ConsensusFinder { rpc_heads: HashMap, Web3ProxyBlock>, /// never serve blocks that are too old - max_block_age: Option, + max_head_block_age: Option, /// tier 0 will be prefered as long as the distance between it and the other tiers is <= max_tier_lag max_block_lag: Option, /// Block Hash -> First Seen Instant. used to track rpc.head_latency. The same cache should be shared between all ConnectionsGroups @@ -347,7 +347,7 @@ pub struct ConsensusFinder { } impl ConsensusFinder { - pub fn new(max_block_age: Option, max_block_lag: Option) -> Self { + pub fn new(max_head_block_age: Option, max_block_lag: Option) -> Self { // TODO: what's a good capacity for this? it shouldn't need to be very large let first_seen = Cache::new(16); @@ -355,7 +355,7 @@ impl ConsensusFinder { Self { rpc_heads, - max_block_age, + max_head_block_age, max_block_lag, first_seen, } @@ -406,7 +406,7 @@ impl ConsensusFinder { .await .web3_context("failed caching block")?; - if let Some(max_age) = self.max_block_age { + if let Some(max_age) = self.max_head_block_age { if rpc_head_block.age() > max_age { trace!("rpc_head_block from {} is too old! {}", rpc, rpc_head_block); return Ok(self.remove(&rpc).is_some()); @@ -536,6 +536,7 @@ impl ConsensusFinder { trace!("lowest_block_number: {}", lowest_block.number()); + // TODO: move this default. should be in config, not here let max_lag_block_number = highest_block_number.saturating_sub(self.max_block_lag.unwrap_or_else(|| U64::from(5))); diff --git a/web3_proxy/src/rpcs/many.rs b/web3_proxy/src/rpcs/many.rs index 54e8f61d..043fb7dd 100644 --- a/web3_proxy/src/rpcs/many.rs +++ b/web3_proxy/src/rpcs/many.rs @@ -68,7 +68,7 @@ pub struct Web3Rpcs { /// how far behind the highest known block height we can be before we stop serving requests pub(super) max_block_lag: Option, /// how old our consensus head block we can be before we stop serving requests - pub(super) max_block_age: Option, + pub(super) max_head_block_age: Option, } impl Web3Rpcs { @@ -76,7 +76,7 @@ impl Web3Rpcs { #[allow(clippy::too_many_arguments)] pub async fn spawn( db_conn: Option, - max_block_age: Option, + max_head_block_age: Option, max_block_lag: Option, min_head_rpcs: usize, min_sum_soft_limit: u32, @@ -120,7 +120,7 @@ impl Web3Rpcs { blocks_by_hash, blocks_by_number, by_name, - max_block_age, + max_head_block_age, max_block_lag, min_synced_rpcs: min_head_rpcs, min_sum_soft_limit, @@ -1526,8 +1526,8 @@ mod tests { blocks_by_number: CacheBuilder::new(100) .time_to_live(Duration::from_secs(60)) .build(), - // TODO: test max_block_age? - max_block_age: None, + // TODO: test max_head_block_age? + max_head_block_age: None, // TODO: test max_block_lag? max_block_lag: None, min_synced_rpcs: 1, @@ -1808,7 +1808,7 @@ mod tests { .build(), min_synced_rpcs: 1, min_sum_soft_limit: 4_000, - max_block_age: None, + max_head_block_age: None, max_block_lag: None, }; @@ -1988,7 +1988,7 @@ mod tests { blocks_by_number: Cache::new(10_000), min_synced_rpcs: 1, min_sum_soft_limit: 1_000, - max_block_age: None, + max_head_block_age: None, max_block_lag: None, };