From 9d5702406439372990bf7286a50992e080f9eae6 Mon Sep 17 00:00:00 2001 From: Joe Parks <26990067+jowparks@users.noreply.github.com> Date: Mon, 21 Apr 2025 16:18:17 -0700 Subject: [PATCH] Add 'call' metric to Metrics struct and implement EthApiOverride::call method This commit introduces a new metric for tracking the count of times the 'call' method is invoked. Additionally, the EthApiOverride trait is updated to include the 'call' method, which processes transaction requests and interacts with the pending block state. --- src/metrics.rs | 3 +++ src/rpc.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/metrics.rs b/src/metrics.rs index 5cf39b8..4441908 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -26,4 +26,7 @@ pub struct Metrics { #[metric(describe = "Count of times flashblocks get_block_by_number is called")] pub get_block_by_number: Counter, + + #[metric(describe = "Count of times flashblocks call is called")] + pub call: Counter, } diff --git a/src/rpc.rs b/src/rpc.rs index cc65c09..0ade6bc 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -6,8 +6,8 @@ use alloy_consensus::transaction::TransactionMeta; use alloy_consensus::{transaction::Recovered, transaction::TransactionInfo}; use alloy_eips::{BlockId, BlockNumberOrTag}; use alloy_primitives::{Address, Sealable, TxHash, U256}; -use alloy_rpc_types::TransactionTrait; use alloy_rpc_types::{BlockTransactions, Header}; +use alloy_rpc_types::{Bundle, StateContext, TransactionRequest, TransactionTrait}; use jsonrpsee::{ core::{async_trait, RpcResult}, proc_macros::rpc, @@ -19,7 +19,7 @@ use reth::{api::BlockBody, providers::HeaderProvider}; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_primitives::{OpBlock, OpReceipt, OpTransactionSigned}; use reth_optimism_rpc::OpReceiptBuilder; -use reth_rpc_eth_api::helpers::EthTransactions; +use reth_rpc_eth_api::helpers::{EthCall, EthTransactions}; use reth_rpc_eth_api::RpcReceipt; use reth_rpc_eth_api::{helpers::FullEthApi, RpcBlock}; use reth_rpc_eth_api::{ @@ -54,6 +54,13 @@ pub trait EthApiOverride { address: Address, block_number: Option, ) -> RpcResult; + + #[method(name = "call")] + async fn call( + &self, + transaction: TransactionRequest, + block_number: Option, + ) -> RpcResult; } #[derive(Debug)] @@ -341,4 +348,50 @@ where .await .map_err(Into::into) } + + async fn call( + &self, + transaction: TransactionRequest, + block_number: Option, + ) -> RpcResult { + // Check if this is a call to the pending block + let block_id = block_number.unwrap_or_default(); + + if block_id.is_pending() { + self.metrics.call.increment(1); + + let mut transaction_requests = self + .cache + .get::("pending") + .unwrap_or_default() + .body + .transactions + .iter() + .map(|tx| TransactionRequest::from_transaction(tx.clone())) + .collect::>(); + + transaction_requests.push(transaction); + let bundles = vec![Bundle::from(transaction_requests)]; + + let context = StateContext { + block_number: Some(BlockId::Number(BlockNumberOrTag::Pending)), + transaction_index: None, + }; + return EthCall::call_many(&self.eth_api, bundles, Some(context), None) + .await + .map_err(Into::into) + .map(|responses| { + responses + .first() + .map_or_else(alloy_primitives::Bytes::default, |r| { + r.clone().value.unwrap_or_default() + }) + }); + } + let overrides = alloy_rpc_types_eth::state::EvmOverrides::default(); + // Delegate to the underlying eth_api + EthCall::call(&self.eth_api, transaction, block_number, overrides) + .await + .map_err(Into::into) + } }