From 7642a444c40cf8116f03b3be3bc2e7b0ea80b4f9 Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Sat, 10 May 2025 16:57:36 +0530 Subject: [PATCH 1/8] feat: support getAccount mode --- src/backend.rs | 61 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index fb42353..f782d16 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -36,6 +36,7 @@ use std::{ Arc, }, }; +use tokio::sync::Mutex; /// Logged when an error is indicative that the user is trying to fork from a non-archive node. pub const NON_ARCHIVE_NODE_WARNING: &str = "\ @@ -139,6 +140,16 @@ enum BackendRequest { AnyRequest(Box), } +/// Mode for fetching account data from the provider +#[derive(Debug, Default, Clone)] +enum GetAccountMode { + /// The provider supports `eth_getAccountInfo` + #[default] + EthGetAccountInfo, + /// Must fetch balance, nonce, and code concurrently + AccountCodeNonce, +} + /// Handles an internal provider and listens for requests. /// /// This handler will remain active as long as it is reachable (request channel still open) and @@ -163,6 +174,8 @@ pub struct BackendHandler

{ /// The block to fetch data from. // This is an `Option` so that we can have less code churn in the functions below block_id: Option, + /// The mode for fetching account data + account_fetch_mode: GetAccountMode, } impl

BackendHandler

@@ -185,6 +198,7 @@ where queued_requests: Default::default(), incoming: rx, block_id, + account_fetch_mode: Default::default(), } } @@ -279,18 +293,48 @@ where } /// returns the future that fetches the account data - fn get_account_req(&self, address: Address) -> ProviderRequest { + fn get_account_req(&mut self, address: Address) -> ProviderRequest { trace!(target: "backendhandler", "preparing account request, address={:?}", address); let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); + let mode = Arc::new(Mutex::new(self.account_fetch_mode.clone())); + let mode_clone = Arc::clone(&mode); + let fut = Box::pin(async move { - let balance = provider.get_balance(address).block_id(block_id).into_future(); - let nonce = provider.get_transaction_count(address).block_id(block_id).into_future(); - let code = provider.get_code_at(address).block_id(block_id).into_future(); - let resp = tokio::try_join!(balance, nonce, code).map_err(Into::into); - (resp, address) + let mut mode = mode_clone.lock().await; + + match *mode { + GetAccountMode::EthGetAccountInfo => { + match provider.get_account_info(address).block_id(block_id).await { + Ok(info) => Ok((info.balance, info.nonce, info.code)), + Err(_) => { + *mode = GetAccountMode::AccountCodeNonce; + let balance = + provider.get_balance(address).block_id(block_id).into_future(); + let nonce = provider + .get_transaction_count(address) + .block_id(block_id) + .into_future(); + let code = + provider.get_code_at(address).block_id(block_id).into_future(); + tokio::try_join!(balance, nonce, code).map_err(Into::into) + } + } + } + GetAccountMode::AccountCodeNonce => { + let balance = provider.get_balance(address).block_id(block_id).into_future(); + let nonce = + provider.get_transaction_count(address).block_id(block_id).into_future(); + let code = provider.get_code_at(address).block_id(block_id).into_future(); + tokio::try_join!(balance, nonce, code).map_err(Into::into) + } + } }); - ProviderRequest::Account(fut) + + ProviderRequest::Account(Box::pin(async move { + let result = fut.await; + (result, address) + })) } /// process a request for an account @@ -301,7 +345,8 @@ where } Entry::Vacant(entry) => { entry.insert(vec![listener]); - self.pending_requests.push(self.get_account_req(address)); + let account_req = self.get_account_req(address); + self.pending_requests.push(account_req); } } } From 35edaa3161886214934ed4f90949f486cbccaac0 Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Sun, 11 May 2025 11:20:52 +0530 Subject: [PATCH 2/8] fixes --- src/backend.rs | 67 ++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index f782d16..c2d0d74 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -32,11 +32,11 @@ use std::{ path::Path, pin::Pin, sync::{ + atomic::{AtomicU8, Ordering}, mpsc::{channel as oneshot_channel, Sender as OneshotSender}, Arc, }, }; -use tokio::sync::Mutex; /// Logged when an error is indicative that the user is trying to fork from a non-archive node. pub const NON_ARCHIVE_NODE_WARNING: &str = "\ @@ -65,6 +65,11 @@ type AddressData = AddressHashMap; type StorageData = AddressHashMap; type BlockHashData = HashMap; +/// Constants for account fetching modes +const ACCOUNT_FETCH_UNCHECKED: u8 = 0; +const ACCOUNT_FETCH_SUPPORTS_ACC_INFO: u8 = 1; +const ACCOUNT_FETCH_SEPARATE_REQUESTS: u8 = 2; + struct AnyRequestFuture { sender: OneshotSender>, future: Pin> + Send>>, @@ -140,16 +145,6 @@ enum BackendRequest { AnyRequest(Box), } -/// Mode for fetching account data from the provider -#[derive(Debug, Default, Clone)] -enum GetAccountMode { - /// The provider supports `eth_getAccountInfo` - #[default] - EthGetAccountInfo, - /// Must fetch balance, nonce, and code concurrently - AccountCodeNonce, -} - /// Handles an internal provider and listens for requests. /// /// This handler will remain active as long as it is reachable (request channel still open) and @@ -175,7 +170,7 @@ pub struct BackendHandler

{ // This is an `Option` so that we can have less code churn in the functions below block_id: Option, /// The mode for fetching account data - account_fetch_mode: GetAccountMode, + account_fetch_mode: Arc, } impl

BackendHandler

@@ -198,7 +193,7 @@ where queued_requests: Default::default(), incoming: rx, block_id, - account_fetch_mode: Default::default(), + account_fetch_mode: Arc::new(AtomicU8::new(ACCOUNT_FETCH_UNCHECKED)), } } @@ -297,37 +292,45 @@ where trace!(target: "backendhandler", "preparing account request, address={:?}", address); let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); - let mode = Arc::new(Mutex::new(self.account_fetch_mode.clone())); - let mode_clone = Arc::clone(&mode); + let mode = Arc::clone(&self.account_fetch_mode); let fut = Box::pin(async move { - let mut mode = mode_clone.lock().await; - - match *mode { - GetAccountMode::EthGetAccountInfo => { + match mode.load(Ordering::Relaxed) { + ACCOUNT_FETCH_UNCHECKED | ACCOUNT_FETCH_SUPPORTS_ACC_INFO => { match provider.get_account_info(address).block_id(block_id).await { - Ok(info) => Ok((info.balance, info.nonce, info.code)), - Err(_) => { - *mode = GetAccountMode::AccountCodeNonce; - let balance = - provider.get_balance(address).block_id(block_id).into_future(); - let nonce = provider - .get_transaction_count(address) - .block_id(block_id) - .into_future(); - let code = - provider.get_code_at(address).block_id(block_id).into_future(); - tokio::try_join!(balance, nonce, code).map_err(Into::into) + Ok(info) => { + if mode.load(Ordering::Relaxed) == ACCOUNT_FETCH_UNCHECKED { + mode.store(ACCOUNT_FETCH_SUPPORTS_ACC_INFO, Ordering::Relaxed); + } + Ok((info.balance, info.nonce, info.code)) + } + Err(err) => { + if mode.load(Ordering::Relaxed) == ACCOUNT_FETCH_UNCHECKED { + mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); + // Try the separate requests approach + let balance = + provider.get_balance(address).block_id(block_id).into_future(); + let nonce = provider + .get_transaction_count(address) + .block_id(block_id) + .into_future(); + let code = + provider.get_code_at(address).block_id(block_id).into_future(); + tokio::try_join!(balance, nonce, code).map_err(Into::into) + } else { + Err(err.into()) + } } } } - GetAccountMode::AccountCodeNonce => { + ACCOUNT_FETCH_SEPARATE_REQUESTS => { let balance = provider.get_balance(address).block_id(block_id).into_future(); let nonce = provider.get_transaction_count(address).block_id(block_id).into_future(); let code = provider.get_code_at(address).block_id(block_id).into_future(); tokio::try_join!(balance, nonce, code).map_err(Into::into) } + _ => unreachable!("Invalid account fetch mode"), } }); From ef9e9d318828133f3615645f76c5f69eb8a42229 Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Fri, 23 May 2025 20:07:23 +0530 Subject: [PATCH 3/8] fixes --- src/backend.rs | 76 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index c2d0d74..ddd884d 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -288,41 +288,72 @@ where } /// returns the future that fetches the account data - fn get_account_req(&mut self, address: Address) -> ProviderRequest { + fn get_account_req(&mut self, address: Address) -> ProviderRequest { trace!(target: "backendhandler", "preparing account request, address={:?}", address); + let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); let mode = Arc::clone(&self.account_fetch_mode); let fut = Box::pin(async move { match mode.load(Ordering::Relaxed) { - ACCOUNT_FETCH_UNCHECKED | ACCOUNT_FETCH_SUPPORTS_ACC_INFO => { - match provider.get_account_info(address).block_id(block_id).await { - Ok(info) => { - if mode.load(Ordering::Relaxed) == ACCOUNT_FETCH_UNCHECKED { - mode.store(ACCOUNT_FETCH_SUPPORTS_ACC_INFO, Ordering::Relaxed); + ACCOUNT_FETCH_UNCHECKED => { + let acc_info_fut = provider.get_account_info(address).block_id(block_id); + + let triple_handle = tokio::task::spawn({ + let provider = provider.clone(); + async move { + let balance_fut = + provider.get_balance(address).block_id(block_id).into_future(); + let nonce_fut = provider + .get_transaction_count(address) + .block_id(block_id) + .into_future(); + let code_fut = + provider.get_code_at(address).block_id(block_id).into_future(); + tokio::try_join!(balance_fut, nonce_fut, code_fut) + } + }); + + futures::pin_mut!(triple_handle); + + tokio::select! { + acc_info = acc_info_fut => { + match acc_info { + Ok(info) => { + mode.store(ACCOUNT_FETCH_SUPPORTS_ACC_INFO, Ordering::Relaxed); + Ok((info.balance, info.nonce, info.code)) + } + Err(_) => { + mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); + match triple_handle.await { + Ok(Ok((balance, nonce, code))) => Ok((balance, nonce, code)), + Ok(Err(err)) => Err(err.into()), + Err(join_err) => Err(join_err.into()), + } + } } - Ok((info.balance, info.nonce, info.code)) } - Err(err) => { - if mode.load(Ordering::Relaxed) == ACCOUNT_FETCH_UNCHECKED { - mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); - // Try the separate requests approach - let balance = - provider.get_balance(address).block_id(block_id).into_future(); - let nonce = provider - .get_transaction_count(address) - .block_id(block_id) - .into_future(); - let code = - provider.get_code_at(address).block_id(block_id).into_future(); - tokio::try_join!(balance, nonce, code).map_err(Into::into) - } else { - Err(err.into()) + triple = &mut triple_handle => { + match triple { + Ok(Ok((balance, nonce, code))) => { + mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); + Ok((balance, nonce, code)) + } + Ok(Err(err)) => Err(err.into()), + Err(join_err) => Err(join_err.into()), } } } } + + ACCOUNT_FETCH_SUPPORTS_ACC_INFO => { + match provider.get_account_info(address).block_id(block_id).await { + Ok(info) => Ok((info.balance, info.nonce, info.code)), + Err(err) => Err(err.into()), + } + } + ACCOUNT_FETCH_SEPARATE_REQUESTS => { let balance = provider.get_balance(address).block_id(block_id).into_future(); let nonce = @@ -330,6 +361,7 @@ where let code = provider.get_code_at(address).block_id(block_id).into_future(); tokio::try_join!(balance, nonce, code).map_err(Into::into) } + _ => unreachable!("Invalid account fetch mode"), } }); From 84f8a30768b108de8900d7e5029cb7ba9d829caa Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:23:40 +0530 Subject: [PATCH 4/8] fixes --- src/backend.rs | 64 ++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index ddd884d..c7db1f2 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -288,7 +288,7 @@ where } /// returns the future that fetches the account data - fn get_account_req(&mut self, address: Address) -> ProviderRequest { + fn get_account_req(&self, address: Address) -> ProviderRequest { trace!(target: "backendhandler", "preparing account request, address={:?}", address); let provider = self.provider.clone(); @@ -296,26 +296,15 @@ where let mode = Arc::clone(&self.account_fetch_mode); let fut = Box::pin(async move { - match mode.load(Ordering::Relaxed) { + let initial_mode = mode.load(Ordering::Relaxed); + match initial_mode { ACCOUNT_FETCH_UNCHECKED => { let acc_info_fut = provider.get_account_info(address).block_id(block_id); - - let triple_handle = tokio::task::spawn({ - let provider = provider.clone(); - async move { - let balance_fut = - provider.get_balance(address).block_id(block_id).into_future(); - let nonce_fut = provider - .get_transaction_count(address) - .block_id(block_id) - .into_future(); - let code_fut = - provider.get_code_at(address).block_id(block_id).into_future(); - tokio::try_join!(balance_fut, nonce_fut, code_fut) - } - }); - - futures::pin_mut!(triple_handle); + let balance_fut = + provider.get_balance(address).block_id(block_id).into_future(); + let nonce_fut = + provider.get_transaction_count(address).block_id(block_id).into_future(); + let code_fut = provider.get_code_at(address).block_id(block_id).into_future(); tokio::select! { acc_info = acc_info_fut => { @@ -326,40 +315,37 @@ where } Err(_) => { mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); - match triple_handle.await { - Ok(Ok((balance, nonce, code))) => Ok((balance, nonce, code)), - Ok(Err(err)) => Err(err.into()), - Err(join_err) => Err(join_err.into()), - } + tokio::try_join!(balance_fut, nonce_fut, code_fut).map_err(Into::into) } } } - triple = &mut triple_handle => { + triple = async { tokio::try_join!(balance_fut, nonce_fut, code_fut) } => { match triple { - Ok(Ok((balance, nonce, code))) => { + Ok((balance, nonce, code)) => { mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); Ok((balance, nonce, code)) } - Ok(Err(err)) => Err(err.into()), - Err(join_err) => Err(join_err.into()), + Err(err) => Err(err.into()) } } } } - ACCOUNT_FETCH_SUPPORTS_ACC_INFO => { - match provider.get_account_info(address).block_id(block_id).await { - Ok(info) => Ok((info.balance, info.nonce, info.code)), - Err(err) => Err(err.into()), - } - } + ACCOUNT_FETCH_SUPPORTS_ACC_INFO => provider + .get_account_info(address) + .block_id(block_id) + .await + .map(|info| (info.balance, info.nonce, info.code)) + .map_err(Into::into), ACCOUNT_FETCH_SEPARATE_REQUESTS => { - let balance = provider.get_balance(address).block_id(block_id).into_future(); - let nonce = - provider.get_transaction_count(address).block_id(block_id).into_future(); - let code = provider.get_code_at(address).block_id(block_id).into_future(); - tokio::try_join!(balance, nonce, code).map_err(Into::into) + let (balance, nonce, code) = tokio::try_join!( + provider.get_balance(address).block_id(block_id), + provider.get_transaction_count(address).block_id(block_id), + provider.get_code_at(address).block_id(block_id) + ) + .map_err(Into::into)?; + Ok((balance, nonce, code)) } _ => unreachable!("Invalid account fetch mode"), From 626124ec0c4dbf27a46c1533d1f3d1529d696879 Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Wed, 11 Jun 2025 22:43:12 +0530 Subject: [PATCH 5/8] fixes --- src/backend.rs | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index c7db1f2..1b6e524 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -10,9 +10,10 @@ use alloy_provider::{ Provider, }; use alloy_rpc_types::BlockId; -use eyre::WrapErr; +use eyre::{Report, WrapErr}; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, + pin_mut, stream::Stream, task::{Context, Poll}, Future, FutureExt, @@ -37,6 +38,7 @@ use std::{ Arc, }, }; +use tokio::select; /// Logged when an error is indicative that the user is trying to fork from a non-archive node. pub const NON_ARCHIVE_NODE_WARNING: &str = "\ @@ -288,26 +290,27 @@ where } /// returns the future that fetches the account data - fn get_account_req(&self, address: Address) -> ProviderRequest { + fn get_account_req(&self, address: Address) -> ProviderRequest { trace!(target: "backendhandler", "preparing account request, address={:?}", address); let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); let mode = Arc::clone(&self.account_fetch_mode); - let fut = Box::pin(async move { let initial_mode = mode.load(Ordering::Relaxed); match initial_mode { ACCOUNT_FETCH_UNCHECKED => { - let acc_info_fut = provider.get_account_info(address).block_id(block_id); + let acc_info_fut = + provider.get_account_info(address).block_id(block_id).into_future(); let balance_fut = provider.get_balance(address).block_id(block_id).into_future(); let nonce_fut = provider.get_transaction_count(address).block_id(block_id).into_future(); let code_fut = provider.get_code_at(address).block_id(block_id).into_future(); - - tokio::select! { - acc_info = acc_info_fut => { + let triple_fut = futures::future::try_join3(balance_fut, nonce_fut, code_fut); + pin_mut!(acc_info_fut, triple_fut); + select! { + acc_info = &mut acc_info_fut => { match acc_info { Ok(info) => { mode.store(ACCOUNT_FETCH_SUPPORTS_ACC_INFO, Ordering::Relaxed); @@ -315,17 +318,18 @@ where } Err(_) => { mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); - tokio::try_join!(balance_fut, nonce_fut, code_fut).map_err(Into::into) + triple_fut.await + .map_err(|e| Report::new(e).wrap_err("Failed to fetch account data")) } } } - triple = async { tokio::try_join!(balance_fut, nonce_fut, code_fut) } => { + triple = &mut triple_fut => { match triple { Ok((balance, nonce, code)) => { mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); Ok((balance, nonce, code)) } - Err(err) => Err(err.into()) + Err(e) => Err(Report::new(e).wrap_err("Failed to fetch account data")) } } } @@ -334,18 +338,26 @@ where ACCOUNT_FETCH_SUPPORTS_ACC_INFO => provider .get_account_info(address) .block_id(block_id) + .into_future() .await .map(|info| (info.balance, info.nonce, info.code)) - .map_err(Into::into), + .map_err(|e| Report::new(e).wrap_err("Failed to fetch account info")), ACCOUNT_FETCH_SEPARATE_REQUESTS => { - let (balance, nonce, code) = tokio::try_join!( - provider.get_balance(address).block_id(block_id), - provider.get_transaction_count(address).block_id(block_id), - provider.get_code_at(address).block_id(block_id) - ) - .map_err(Into::into)?; - Ok((balance, nonce, code)) + let balance_fut = + provider.get_balance(address).block_id(block_id).into_future(); + + let nonce_fut = + provider.get_transaction_count(address).block_id(block_id).into_future(); + + let code_fut = provider.get_code_at(address).block_id(block_id).into_future(); + + futures::future::try_join3(balance_fut, nonce_fut, code_fut) + .await + .map(|(balance, nonce, code)| (balance, nonce, code)) + .map_err(|e| { + Report::new(e).wrap_err("Failed to fetch account data separately") + }) } _ => unreachable!("Invalid account fetch mode"), From 7712e34d021a2ef6a662843a8ee6e8333abde98f Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 28 Jun 2025 11:02:40 +0200 Subject: [PATCH 6/8] optimize for ethgetaccinfo --- src/backend.rs | 65 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index 1b6e524..6d3186d 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -10,7 +10,7 @@ use alloy_provider::{ Provider, }; use alloy_rpc_types::BlockId; -use eyre::{Report, WrapErr}; +use eyre::WrapErr; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, pin_mut, @@ -67,9 +67,12 @@ type AddressData = AddressHashMap; type StorageData = AddressHashMap; type BlockHashData = HashMap; -/// Constants for account fetching modes +/// States for tracking which account endpoints should be used when account info const ACCOUNT_FETCH_UNCHECKED: u8 = 0; +/// Endpoints supports the non standard eth_getAccountInfo which is more efficient than sending 3 +/// separate requests const ACCOUNT_FETCH_SUPPORTS_ACC_INFO: u8 = 1; +/// Use regular individual getCode, getNonce, getBalance calls const ACCOUNT_FETCH_SEPARATE_REQUESTS: u8 = 2; struct AnyRequestFuture { @@ -290,18 +293,22 @@ where } /// returns the future that fetches the account data - fn get_account_req(&self, address: Address) -> ProviderRequest { + fn get_account_req(&self, address: Address) -> ProviderRequest { trace!(target: "backendhandler", "preparing account request, address={:?}", address); let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); let mode = Arc::clone(&self.account_fetch_mode); let fut = Box::pin(async move { + // depending on the tracked mode we can dispatch requests. let initial_mode = mode.load(Ordering::Relaxed); match initial_mode { ACCOUNT_FETCH_UNCHECKED => { + // single request for accountinfo object let acc_info_fut = provider.get_account_info(address).block_id(block_id).into_future(); + + // tri request for account info let balance_fut = provider.get_balance(address).block_id(block_id).into_future(); let nonce_fut = @@ -309,17 +316,19 @@ where let code_fut = provider.get_code_at(address).block_id(block_id).into_future(); let triple_fut = futures::future::try_join3(balance_fut, nonce_fut, code_fut); pin_mut!(acc_info_fut, triple_fut); + select! { acc_info = &mut acc_info_fut => { match acc_info { Ok(info) => { + trace!(target: "backendhandler", "endpoint supports eth_getAccountInfo"); mode.store(ACCOUNT_FETCH_SUPPORTS_ACC_INFO, Ordering::Relaxed); Ok((info.balance, info.nonce, info.code)) } - Err(_) => { + Err(err) => { + trace!(target: "backendhandler", ?err, "failed initial eth_getAccountInfo call"); mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); - triple_fut.await - .map_err(|e| Report::new(e).wrap_err("Failed to fetch account data")) + Ok(triple_fut.await?) } } } @@ -329,35 +338,47 @@ where mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); Ok((balance, nonce, code)) } - Err(e) => Err(Report::new(e).wrap_err("Failed to fetch account data")) + Err(err) => Err(err.into()) } } } } - ACCOUNT_FETCH_SUPPORTS_ACC_INFO => provider - .get_account_info(address) - .block_id(block_id) - .into_future() - .await - .map(|info| (info.balance, info.nonce, info.code)) - .map_err(|e| Report::new(e).wrap_err("Failed to fetch account info")), + ACCOUNT_FETCH_SUPPORTS_ACC_INFO => { + let mut res = provider + .get_account_info(address) + .block_id(block_id) + .into_future() + .await + .map(|info| (info.balance, info.nonce, info.code)); + + // it's possible that the configured endpoint load balances requests to multiple + // instances and not all support that endpoint so we should reset here + if res.is_err() { + mode.store(ACCOUNT_FETCH_SEPARATE_REQUESTS, Ordering::Relaxed); + + let balance_fut = + provider.get_balance(address).block_id(block_id).into_future(); + let nonce_fut = provider + .get_transaction_count(address) + .block_id(block_id) + .into_future(); + let code_fut = + provider.get_code_at(address).block_id(block_id).into_future(); + res = futures::future::try_join3(balance_fut, nonce_fut, code_fut).await; + } + + Ok(res?) + } ACCOUNT_FETCH_SEPARATE_REQUESTS => { let balance_fut = provider.get_balance(address).block_id(block_id).into_future(); - let nonce_fut = provider.get_transaction_count(address).block_id(block_id).into_future(); - let code_fut = provider.get_code_at(address).block_id(block_id).into_future(); - futures::future::try_join3(balance_fut, nonce_fut, code_fut) - .await - .map(|(balance, nonce, code)| (balance, nonce, code)) - .map_err(|e| { - Report::new(e).wrap_err("Failed to fetch account data separately") - }) + Ok(futures::future::try_join3(balance_fut, nonce_fut, code_fut).await?) } _ => unreachable!("Invalid account fetch mode"), From 3c265539f1b81e62b192370e948e012c88008c72 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 28 Jun 2025 11:04:27 +0200 Subject: [PATCH 7/8] style --- src/backend.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index 6d3186d..43dd509 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -399,8 +399,7 @@ where } Entry::Vacant(entry) => { entry.insert(vec![listener]); - let account_req = self.get_account_req(address); - self.pending_requests.push(account_req); + self.pending_requests.push(self.get_account_req(address)); } } } From 71121a07888f719392bf79c391f4e760cb91e19c Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 28 Jun 2025 11:05:26 +0200 Subject: [PATCH 8/8] avoid double box --- src/backend.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index 43dd509..f2410ae 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -299,7 +299,7 @@ where let provider = self.provider.clone(); let block_id = self.block_id.unwrap_or_default(); let mode = Arc::clone(&self.account_fetch_mode); - let fut = Box::pin(async move { + let fut = async move { // depending on the tracked mode we can dispatch requests. let initial_mode = mode.load(Ordering::Relaxed); match initial_mode { @@ -383,7 +383,7 @@ where _ => unreachable!("Invalid account fetch mode"), } - }); + }; ProviderRequest::Account(Box::pin(async move { let result = fut.await;