diff --git a/Cargo.lock b/Cargo.lock index 05d71dbf..79ff44fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,7 +272,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -1356,17 +1356,38 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "atty", "humantime", + "is-terminal", "log", "regex", "termcolor", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "error-chain" version = "0.12.4" @@ -1737,7 +1758,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2170,6 +2191,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -2419,6 +2449,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "io-lifetimes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] + [[package]] name = "ipnet" version = "2.5.1" @@ -2435,6 +2475,18 @@ dependencies = [ "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae5bc6e2eb41c9def29a3e0f1306382807764b9b53112030eff57435667352d" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys 0.42.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2556,9 +2608,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libm" @@ -2566,6 +2618,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +[[package]] +name = "linux-raw-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" + [[package]] name = "lock_api" version = "0.4.8" @@ -2698,7 +2756,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2885,7 +2943,7 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", ] @@ -3074,7 +3132,7 @@ dependencies = [ "redox_syscall", "smallvec", "thread-id", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -3770,6 +3828,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.42.0", +] + [[package]] name = "rustls" version = "0.20.6" @@ -3884,9 +3956,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8744afc95ca462de12c2cea5a56d7e406f3be2b2683d3b05066e1afdba898bc5" +checksum = "3120bc435b8640963ffda698f877610e07e077157e216eb99408d819c344034d" dependencies = [ "async-stream", "async-trait", @@ -3912,9 +3984,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531871fd7d043270d6c26071d48bbdc2e04058e570adf7a8a75d9063c96771e9" +checksum = "d037d297869f0960e56f49b6e8c427660f9cc9c3f867132f4d1014676525dbe7" dependencies = [ "chrono", "clap", @@ -3928,9 +4000,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca4d01381fdcabc3818b6d39c5f1f0c885900af90da638e4001406907462784" +checksum = "c54bacfeb842813c16821e21f9456c358861a448294075184ea1d6307e386d08" dependencies = [ "bae", "heck 0.3.3", @@ -3941,9 +4013,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e73a6b3823f2d02b09e16060a2d547c781557f756755b80f413679bdb2a149e" +checksum = "8b0c22c789077e49c8ff6b1560e6b7a1e5f2a8f91aeebfb9b9e874fa1bc1aa29" dependencies = [ "async-trait", "clap", @@ -5549,43 +5621,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "winreg" version = "0.10.1" diff --git a/entities/Cargo.toml b/entities/Cargo.toml index 94e47f9e..78866eb2 100644 --- a/entities/Cargo.toml +++ b/entities/Cargo.toml @@ -10,6 +10,6 @@ path = "src/mod.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -sea-orm = "0.10.3" +sea-orm = "0.10.4" serde = "1.0.147" uuid = "1.2.2" diff --git a/migration/Cargo.toml b/migration/Cargo.toml index 57679780..417680d2 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -12,7 +12,7 @@ path = "src/lib.rs" tokio = { version = "1.22.0", features = ["full", "tracing"] } [dependencies.sea-orm-migration] -version = "0.10.3" +version = "0.10.4" features = [ # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. diff --git a/web3_proxy/Cargo.toml b/web3_proxy/Cargo.toml index 15e7f02c..4770a7b9 100644 --- a/web3_proxy/Cargo.toml +++ b/web3_proxy/Cargo.toml @@ -31,7 +31,7 @@ counter = "0.5.7" derive_more = "0.99.17" dotenv = "0.15.0" ethers = { version = "1.0.1", default-features = false, features = ["rustls", "ws"] } -env_logger = "0.9.3" +env_logger = "0.10.0" fdlimit = "0.2.1" flume = "0.10.14" futures = { version = "0.3.25", features = ["thread-pool"] } diff --git a/web3_proxy/src/bin/web3_proxy.rs b/web3_proxy/src/bin/web3_proxy.rs index 995c0ca7..56f2a526 100644 --- a/web3_proxy/src/bin/web3_proxy.rs +++ b/web3_proxy/src/bin/web3_proxy.rs @@ -294,27 +294,29 @@ mod tests { balanced_rpcs: HashMap::from([ ( "anvil".to_string(), - Web3ConnectionConfig::new( - false, - None, - anvil.endpoint(), - 100, - None, - 1, - Some(false), - ), + Web3ConnectionConfig { + disabled: false, + display_name: None, + url: anvil.endpoint(), + block_data_limit: None, + soft_limit: 100, + hard_limit: None, + weight: 1, + subscribe_txs: Some(false), + }, ), ( "anvil_ws".to_string(), - Web3ConnectionConfig::new( - false, - None, - anvil.ws_endpoint(), - 100, - None, - 0, - Some(true), - ), + Web3ConnectionConfig { + disabled: false, + display_name: None, + url: anvil.ws_endpoint(), + block_data_limit: None, + soft_limit: 100, + hard_limit: None, + weight: 1, + subscribe_txs: Some(false), + }, ), ]), private_rpcs: None, diff --git a/web3_proxy/src/config.rs b/web3_proxy/src/config.rs index e001b2df..98a38d22 100644 --- a/web3_proxy/src/config.rs +++ b/web3_proxy/src/config.rs @@ -3,7 +3,6 @@ use crate::rpcs::connection::Web3Connection; use crate::rpcs::request::OpenRequestHandleMetrics; use crate::{app::AnyhowJoinHandle, rpcs::blockchain::ArcBlock}; use argh::FromArgs; -use derive_more::Constructor; use ethers::prelude::TxHash; use hashbrown::HashMap; use migration::sea_orm::DatabaseConnection; @@ -176,7 +175,7 @@ fn default_response_cache_max_bytes() -> usize { } /// Configuration for a backend web3 RPC server -#[derive(Debug, Deserialize, Constructor)] +#[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] pub struct Web3ConnectionConfig { /// simple way to disable a connection without deleting the row @@ -186,6 +185,8 @@ pub struct Web3ConnectionConfig { pub display_name: Option, /// websocket (or http if no websocket) pub url: String, + /// block data limit. If None, will be queried + pub block_data_limit: Option, /// the requests per second at which the server starts slowing down pub soft_limit: u32, /// the requests per second at which the server throws errors (rate limit or otherwise) @@ -247,6 +248,7 @@ impl Web3ConnectionConfig { http_interval_sender, hard_limit, self.soft_limit, + self.block_data_limit, block_map, block_sender, tx_id_sender, diff --git a/web3_proxy/src/frontend/authorization.rs b/web3_proxy/src/frontend/authorization.rs index 06fa11ec..254346ad 100644 --- a/web3_proxy/src/frontend/authorization.rs +++ b/web3_proxy/src/frontend/authorization.rs @@ -45,6 +45,12 @@ pub enum RateLimitResult { UnknownKey, } +#[derive(Clone, Debug)] +pub enum AuthorizatioType { + Internal, + Frontend, +} + /// TODO: include the authorization checks in this? #[derive(Clone, Debug)] pub struct Authorization { @@ -54,6 +60,7 @@ pub struct Authorization { pub origin: Option, pub referer: Option, pub user_agent: Option, + pub authorization_type: AuthorizatioType, } #[derive(Debug)] @@ -163,7 +170,7 @@ impl From for Uuid { } impl Authorization { - pub fn local(db_conn: Option) -> anyhow::Result { + pub fn internal(db_conn: Option) -> anyhow::Result { let authorization_checks = AuthorizationChecks { // any error logs on a local (internal) query are likely problems. log them all log_revert_chance: 1.0, @@ -174,10 +181,18 @@ impl Authorization { let ip: IpAddr = "127.0.0.1".parse().expect("localhost should always parse"); let user_agent = UserAgent::from_str(APP_USER_AGENT).ok(); - Self::try_new(authorization_checks, db_conn, ip, None, None, user_agent) + Self::try_new( + authorization_checks, + db_conn, + ip, + None, + None, + user_agent, + AuthorizatioType::Internal, + ) } - pub fn public( + pub fn external( allowed_origin_requests_per_period: &HashMap, db_conn: Option, ip: IpAddr, @@ -208,6 +223,7 @@ impl Authorization { origin, referer, user_agent, + AuthorizatioType::Frontend, ) } @@ -218,6 +234,7 @@ impl Authorization { origin: Option, referer: Option, user_agent: Option, + authorization_type: AuthorizatioType, ) -> anyhow::Result { // check ip match &authorization_checks.allowed_ips { @@ -272,6 +289,7 @@ impl Authorization { origin, referer, user_agent, + authorization_type, }) } } @@ -444,7 +462,7 @@ impl Web3ProxyApp { // TODO: dry this up with rate_limit_by_rpc_key? // we don't care about user agent or origin or referer - let authorization = Authorization::public( + let authorization = Authorization::external( &self.config.allowed_origin_requests_per_period, self.db_conn(), ip, @@ -498,7 +516,7 @@ impl Web3ProxyApp { ) -> anyhow::Result { // ip rate limits don't check referer or user agent // the do check - let authorization = Authorization::public( + let authorization = Authorization::external( allowed_origin_requests_per_period, self.db_conn.clone(), ip, @@ -687,6 +705,7 @@ impl Web3ProxyApp { origin, referer, user_agent, + AuthorizatioType::Frontend, )?; let user_max_requests_per_period = match authorization.checks.max_requests_per_period { diff --git a/web3_proxy/src/rpcs/connection.rs b/web3_proxy/src/rpcs/connection.rs index 26136186..dcafa05d 100644 --- a/web3_proxy/src/rpcs/connection.rs +++ b/web3_proxy/src/rpcs/connection.rs @@ -9,7 +9,7 @@ use anyhow::Context; use ethers::prelude::{Bytes, Middleware, ProviderError, TxHash, H256, U64}; use futures::future::try_join_all; use futures::StreamExt; -use log::{debug, error, info, warn, Level}; +use log::{debug, error, info, trace, warn, Level}; use migration::sea_orm::DatabaseConnection; use parking_lot::RwLock; use redis_rate_limiter::{RedisPool, RedisRateLimitResult, RedisRateLimiter}; @@ -37,10 +37,10 @@ pub struct Web3Connection { pub(super) http_client: Option, /// keep track of currently open requests. We sort on this pub(super) active_requests: AtomicU32, - /// keep track of total requests - /// TODO: is this type okay? - /// TODO: replace this with something in metered? - pub(super) total_requests: AtomicU64, + /// keep track of total requests from the frontend + pub(super) frontend_requests: AtomicU64, + /// keep track of total requests from web3-proxy itself + pub(super) internal_requests: AtomicU64, /// provider is in a RwLock so that we can replace it if re-connecting /// it is an async lock because we hold it open across awaits pub(super) provider: AsyncRwLock>>, @@ -75,6 +75,7 @@ impl Web3Connection { hard_limit: Option<(u64, RedisPool)>, // TODO: think more about this type soft_limit: u32, + block_data_limit: Option, block_map: BlockHashesCache, block_sender: Option>, tx_id_sender: Option)>>, @@ -96,17 +97,20 @@ impl Web3Connection { // turn weight 0 into 100% and weight 100 into 0% let weight = (100 - weight) as f64 / 100.0; + let block_data_limit = block_data_limit.unwrap_or_default().into(); + let new_connection = Self { name, display_name, http_client, url: url_str, active_requests: 0.into(), - total_requests: 0.into(), + frontend_requests: 0.into(), + internal_requests: 0.into(), provider: AsyncRwLock::new(None), hard_limit, soft_limit, - block_data_limit: Default::default(), + block_data_limit, head_block_id: RwLock::new(Default::default()), weight, open_request_handle_metrics, @@ -119,7 +123,7 @@ impl Web3Connection { .retrying_reconnect(block_sender.as_ref(), false) .await?; - let authorization = Arc::new(Authorization::local(db_conn)?); + let authorization = Arc::new(Authorization::internal(db_conn)?); // check the server's chain_id here // TODO: move this outside the `new` function and into a `start` function or something. that way we can do retries from there @@ -153,7 +157,12 @@ impl Web3Connection { } } - let will_subscribe_to_blocks = block_sender.is_some(); + // TODO: should we do this even if block_sender is None? then we would know limits on private relays + let check_block_limit_needed = (new_connection + .block_data_limit + .load(atomic::Ordering::Acquire) + == 0) + && block_sender.is_some(); // subscribe to new blocks and new transactions // TODO: make transaction subscription optional (just pass None for tx_id_sender) @@ -179,7 +188,7 @@ impl Web3Connection { // TODO: would be great if rpcs exposed this // TODO: move this to a helper function so we can recheck on errors or as the chain grows // TODO: move this to a helper function that checks - if will_subscribe_to_blocks { + if check_block_limit_needed { // TODO: make sure the server isn't still syncing // TODO: don't sleep. wait for new heads subscription instead @@ -194,32 +203,30 @@ impl Web3Connection { Ok((new_connection, handle)) } - /// TODO: should check_block_data_limit take authorization? async fn check_block_data_limit( self: &Arc, authorization: &Arc, ) -> anyhow::Result> { let mut limit = None; - for block_data_limit in [u64::MAX, 90_000, 128, 64, 32] { + // TODO: binary search between 90k and max? + // TODO: start at 0 or 1 + for block_data_limit in [0, 32, 64, 128, 256, 512, 1024, 90_000, u64::MAX] { let mut head_block_id = self.head_block_id.read().clone(); // TODO: subscribe to a channel instead of polling. subscribe to http_interval_sender? while head_block_id.is_none() { warn!("no head block yet. retrying rpc {}", self); + // TODO: sleep for the block time, or maybe subscribe to a channel instead of this simple pull sleep(Duration::from_secs(13)).await; head_block_id = self.head_block_id.read().clone(); } let head_block_num = head_block_id.expect("is_none was checked above").num; - debug_assert_ne!(head_block_num, U64::zero()); - // TODO: subtract 1 from block_data_limit for safety? - let maybe_archive_block = head_block_num - .saturating_sub((block_data_limit).into()) - .max(U64::one()); + let maybe_archive_block = head_block_num.saturating_sub((block_data_limit).into()); // TODO: wait for the handle BEFORE we check the current block number. it might be delayed too! // TODO: what should the request be? @@ -233,17 +240,22 @@ impl Web3Connection { maybe_archive_block, )), // error here are expected, so keep the level low - Level::Debug.into(), + Level::Trace.into(), ) .await; - // // trace!(?archive_result, rpc=%self); - - if archive_result.is_ok() { - limit = Some(block_data_limit); + trace!( + "archive_result on {} for {}: {:?}", + block_data_limit, + self.name, + archive_result + ); + if archive_result.is_err() { break; } + + limit = Some(block_data_limit); } if let Some(limit) = limit { @@ -251,6 +263,8 @@ impl Web3Connection { .store(limit, atomic::Ordering::Release); } + debug!("block data limit on {}: {:?}", self.name, limit); + Ok(limit) } @@ -946,7 +960,7 @@ impl Serialize for Web3Connection { state.serialize_field( "total_requests", - &self.total_requests.load(atomic::Ordering::Relaxed), + &self.frontend_requests.load(atomic::Ordering::Relaxed), )?; let head_block_id = &*self.head_block_id.read(); @@ -999,7 +1013,8 @@ mod tests { url: "ws://example.com".to_string(), http_client: None, active_requests: 0.into(), - total_requests: 0.into(), + frontend_requests: 0.into(), + internal_requests: 0.into(), provider: AsyncRwLock::new(None), hard_limit: None, soft_limit: 1_000, @@ -1027,13 +1042,15 @@ mod tests { let metrics = OpenRequestHandleMetrics::default(); + // TODO: this is getting long. have a `impl Default` let x = Web3Connection { name: "name".to_string(), display_name: None, url: "ws://example.com".to_string(), http_client: None, active_requests: 0.into(), - total_requests: 0.into(), + frontend_requests: 0.into(), + internal_requests: 0.into(), provider: AsyncRwLock::new(None), hard_limit: None, soft_limit: 1_000, diff --git a/web3_proxy/src/rpcs/connections.rs b/web3_proxy/src/rpcs/connections.rs index 5034799c..ad48089a 100644 --- a/web3_proxy/src/rpcs/connections.rs +++ b/web3_proxy/src/rpcs/connections.rs @@ -215,7 +215,7 @@ impl Web3Connections { min_head_rpcs, }); - let authorization = Arc::new(Authorization::local(db_conn.clone())?); + let authorization = Arc::new(Authorization::internal(db_conn.clone())?); let handle = { let connections = connections.clone(); @@ -857,7 +857,8 @@ mod tests { url: "ws://example.com/synced".to_string(), http_client: None, active_requests: 0.into(), - total_requests: 0.into(), + frontend_requests: 0.into(), + internal_requests: 0.into(), provider: AsyncRwLock::new(Some(Arc::new(Web3Provider::Mock))), hard_limit: None, soft_limit: 1_000, @@ -873,7 +874,8 @@ mod tests { url: "ws://example.com/lagged".to_string(), http_client: None, active_requests: 0.into(), - total_requests: 0.into(), + frontend_requests: 0.into(), + internal_requests: 0.into(), provider: AsyncRwLock::new(Some(Arc::new(Web3Provider::Mock))), hard_limit: None, soft_limit: 1_000, @@ -914,7 +916,7 @@ mod tests { min_sum_soft_limit: 1, }; - let authorization = Arc::new(Authorization::local(None).unwrap()); + let authorization = Arc::new(Authorization::internal(None).unwrap()); let (head_block_sender, _head_block_receiver) = watch::channel::(Default::default()); diff --git a/web3_proxy/src/rpcs/request.rs b/web3_proxy/src/rpcs/request.rs index e6e2cc30..1b61a8df 100644 --- a/web3_proxy/src/rpcs/request.rs +++ b/web3_proxy/src/rpcs/request.rs @@ -1,6 +1,6 @@ use super::connection::Web3Connection; use super::provider::Web3Provider; -use crate::frontend::authorization::Authorization; +use crate::frontend::authorization::{AuthorizatioType, Authorization}; use crate::metered::{JsonRpcErrorCount, ProviderErrorCount}; use anyhow::Context; use chrono::Utc; @@ -42,14 +42,16 @@ pub struct OpenRequestHandle { /// Depending on the context, RPC errors can require different handling. pub enum RequestErrorHandler { - /// Potentially save the revert. Users can tune how often this happens - SaveReverts, + /// Log at the trace level. Use when errors are expected. + TraceLevel, /// Log at the debug level. Use when errors are expected. DebugLevel, /// Log at the error level. Use when errors are bad. ErrorLevel, /// Log at the warn level. Use when errors do not cause problems. WarnLevel, + /// Potentially save the revert. Users can tune how often this happens + SaveReverts, } // TODO: second param could be skipped since we don't need it here @@ -65,6 +67,7 @@ struct EthCallFirstParams { impl From for RequestErrorHandler { fn from(level: Level) -> Self { match level { + Level::Trace => RequestErrorHandler::TraceLevel, Level::Debug => RequestErrorHandler::DebugLevel, Level::Error => RequestErrorHandler::ErrorLevel, Level::Warn => RequestErrorHandler::WarnLevel, @@ -136,7 +139,16 @@ impl OpenRequestHandle { // TODO: handle overflows? // TODO: what ordering? - conn.total_requests.fetch_add(1, atomic::Ordering::Relaxed); + match authorization.as_ref().authorization_type { + AuthorizatioType::Frontend => { + conn.frontend_requests + .fetch_add(1, atomic::Ordering::Relaxed); + } + AuthorizatioType::Internal => { + conn.internal_requests + .fetch_add(1, atomic::Ordering::Relaxed); + } + } let metrics = conn.open_request_handle_metrics.clone(); let used = false.into(); @@ -273,6 +285,7 @@ impl OpenRequestHandle { false }; + // TODO: think more about the method and param logs. those can be sensitive information match error_handler { RequestErrorHandler::DebugLevel => { // TODO: think about this revert check more. sometimes we might want reverts logged so this needs a flag @@ -283,19 +296,38 @@ impl OpenRequestHandle { ); } } - RequestErrorHandler::ErrorLevel => { - error!( + RequestErrorHandler::TraceLevel => { + trace!( "bad response from {}! method={} params={:?} err={:?}", - self.conn, method, params, err + self.conn, + method, + params, + err + ); + } + RequestErrorHandler::ErrorLevel => { + // TODO: include params if not running in release mode + error!( + "bad response from {}! method={} err={:?}", + self.conn, method, err ); } RequestErrorHandler::WarnLevel => { + // TODO: include params if not running in release mode warn!( - "bad response from {}! method={} params={:?} err={:?}", - self.conn, method, params, err + "bad response from {}! method={} err={:?}", + self.conn, method, err ); } RequestErrorHandler::SaveReverts => { + trace!( + "bad response from {}! method={} params={:?} err={:?}", + self.conn, + method, + params, + err + ); + // TODO: do not unwrap! (doesn't matter much since we check method as a string above) let method: Method = Method::try_from_value(&method.to_string()).unwrap();