diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 61a190f7e6..6906ecbd4c 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -157,7 +157,7 @@ where TraceApiClient::trace_raw_transaction(client, Bytes::default(), HashSet::default(), None) .await .unwrap_err(); - TraceApiClient::trace_call_many(client, vec![], None).await.err().unwrap(); + TraceApiClient::trace_call_many(client, vec![], None).await.unwrap(); TraceApiClient::replay_transaction(client, H256::default(), HashSet::default()) .await .err() diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 894a5594af..85d7b9273d 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -196,23 +196,22 @@ where f(state) } - async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)> { - // TODO handle Pending state's env - match at { - BlockId::Number(BlockNumberOrTag::Pending) => { - // This should perhaps use the latest env settings and update block specific - // settings like basefee/number - Err(EthApiError::Unsupported("pending state not implemented yet")) - } - hash_or_num => { - let block_hash = self - .client() - .block_hash_for_id(hash_or_num)? - .ok_or_else(|| EthApiError::UnknownBlockNumber)?; - let (cfg, env) = self.cache().get_evm_env(block_hash).await?; - Ok((cfg, env, block_hash.into())) + async fn evm_env_at(&self, mut at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)> { + if at.is_pending() { + if let Some(pending) = self.client().pending_header()? { + let mut cfg = CfgEnv::default(); + let mut block_env = BlockEnv::default(); + self.client().fill_block_env_with_header(&mut block_env, &pending.header)?; + self.client().fill_cfg_env_with_header(&mut cfg, &pending.header)?; + return Ok((cfg, block_env, pending.hash.into())) } + // No pending block, use latest + at = BlockId::Number(BlockNumberOrTag::Latest); } + let block_hash = + self.client().block_hash_for_id(at)?.ok_or_else(|| EthApiError::UnknownBlockNumber)?; + let (cfg, env) = self.cache().get_evm_env(block_hash).await?; + Ok((cfg, env, block_hash.into())) } async fn evm_env_for_raw_block(&self, header: &Header) -> EthResult<(CfgEnv, BlockEnv)> { diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 61762de4db..38f9879750 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -184,6 +184,10 @@ impl BlockProvider for ShareableDatabase { self.provider()?.pending_block() } + fn pending_header(&self) -> Result> { + self.provider()?.pending_header() + } + fn ommers(&self, id: BlockHashOrNumber) -> Result>> { self.provider()?.ommers(id) } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 64dd88c0ad..e52c903048 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -206,6 +206,10 @@ impl<'this, TX: DbTx<'this>> BlockProvider for DatabaseProvider<'this, TX> { Ok(None) } + fn pending_header(&self) -> Result> { + Ok(None) + } + fn ommers(&self, id: BlockHashOrNumber) -> Result>> { if let Some(number) = self.convert_hash_or_number(id)? { // TODO: this can be optimized to return empty Vec post-merge diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 3f1cd55441..a61d2554c8 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -230,6 +230,10 @@ where Ok(self.tree.pending_block()) } + fn pending_header(&self) -> Result> { + Ok(self.tree.pending_header()) + } + fn ommers(&self, id: BlockHashOrNumber) -> Result>> { self.database.provider()?.ommers(id) } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index a94e26a4f1..a3b48578ec 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -306,6 +306,10 @@ impl BlockProvider for MockEthProvider { Ok(None) } + fn pending_header(&self) -> Result> { + Ok(None) + } + fn ommers(&self, _id: BlockHashOrNumber) -> Result>> { Ok(None) } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 24310c620a..bc0cf850d2 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -62,6 +62,10 @@ impl BlockProvider for NoopProvider { Ok(None) } + fn pending_header(&self) -> Result> { + Ok(None) + } + fn ommers(&self, _id: BlockHashOrNumber) -> Result>> { Ok(None) } diff --git a/crates/storage/provider/src/traits/block.rs b/crates/storage/provider/src/traits/block.rs index d8e9ae5470..4f15e4ea32 100644 --- a/crates/storage/provider/src/traits/block.rs +++ b/crates/storage/provider/src/traits/block.rs @@ -64,6 +64,12 @@ pub trait BlockProvider: /// and the caller does not know the hash. fn pending_block(&self) -> Result>; + /// Returns the pending block header if available + /// + /// Note: This returns a [SealedHeader] because it's expected that this is sealed by the + /// provider and the caller does not know the hash. + fn pending_header(&self) -> Result>; + /// Returns the ommers/uncle headers of the given block from the database. /// /// Returns `None` if block is not found.