Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rpc/rpc-eth-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ tokio.workspace = true
# misc
auto_impl.workspace = true
dyn-clone.workspace = true
serde_json.workspace = true
tracing.workspace = true

[features]
Expand Down
28 changes: 19 additions & 9 deletions crates/rpc/rpc-eth-api/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use alloy_serde::JsonStorageKey;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives_traits::TxTy;
use reth_rpc_convert::RpcTxReq;
use reth_rpc_eth_types::FillTransaction;
use reth_rpc_eth_types::{EthApiError, FillTransaction};
use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
use serde_json::Value;
use std::collections::HashMap;
use tracing::trace;

Expand Down Expand Up @@ -406,14 +407,14 @@ pub trait EthApi<

/// Returns the EIP-7928 block access list for a block by hash.
#[method(name = "getBlockAccessListByBlockHash")]
async fn block_access_list_by_block_hash(&self, hash: B256) -> RpcResult<Option<Bytes>>;
async fn block_access_list_by_block_hash(&self, hash: B256) -> RpcResult<Option<Value>>;

/// Returns the EIP-7928 block access list for a block by number.
#[method(name = "getBlockAccessListByBlockNumber")]
async fn block_access_list_by_block_number(
&self,
number: BlockNumberOrTag,
) -> RpcResult<Option<Bytes>>;
) -> RpcResult<Option<Value>>;
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -913,17 +914,26 @@ where
}

/// Handler for: `eth_getBlockAccessListByBlockHash`
async fn block_access_list_by_block_hash(&self, hash: B256) -> RpcResult<Option<Bytes>> {
trace!(target: "rpc::eth", ?hash, "Serving eth_getBlockAccessListByBlockHash");
Err(internal_rpc_err("unimplemented"))
}
async fn block_access_list_by_block_hash(&self, block_hash: B256) -> RpcResult<Option<Value>> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think returning value here makes sense for now, but it has some overhead because we then need to serialize this as string again.

but lets keep it for now

trace!(target: "rpc::eth", ?block_hash, "Serving eth_getBlockAccessListByBlockHash");

let bal = self.get_block_access_list(block_hash.into()).await?;
let json = serde_json::to_value(&bal)
.map_err(|e| EthApiError::Internal(reth_errors::RethError::msg(e.to_string())))?;

Ok(Some(json))
}
/// Handler for: `eth_getBlockAccessListByBlockNumber`
async fn block_access_list_by_block_number(
&self,
number: BlockNumberOrTag,
) -> RpcResult<Option<Bytes>> {
) -> RpcResult<Option<Value>> {
trace!(target: "rpc::eth", ?number, "Serving eth_getBlockAccessListByBlockNumber");
Err(internal_rpc_err("unimplemented"))

let bal = self.get_block_access_list(number.into()).await?;
let json = serde_json::to_value(&bal)
.map_err(|e| EthApiError::Internal(reth_errors::RethError::msg(e.to_string())))?;

Ok(Some(json))
}
}
67 changes: 67 additions & 0 deletions crates/rpc/rpc-eth-api/src/helpers/bal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Helpers for `eth_blockAccessList` RPC method.
use alloy_consensus::BlockHeader;
use alloy_eips::eip7928::BlockAccessList;
use alloy_rpc_types_eth::BlockId;
use reth_errors::RethError;
use reth_evm::{block::BlockExecutor, ConfigureEvm, Evm};
use reth_revm::{database::StateProviderDatabase, State};
use reth_rpc_eth_types::{
cache::db::StateProviderTraitObjWrapper, error::FromEthApiError, EthApiError,
};
use reth_storage_api::StateProviderFactory;

use crate::{
helpers::{Call, LoadBlock, Trace},
RpcNodeCore,
};

/// Helper trait for `eth_blockAccessList` RPC method.
pub trait GetBlockAccessList: Trace + Call + LoadBlock {
/// Retrieves the block access list for a block identified by its hash.
fn get_block_access_list(
&self,
block_id: BlockId,
) -> impl Future<Output = Result<Option<BlockAccessList>, Self::Error>> + Send {
async move {
let block = self
.recovered_block(block_id)
.await?
.ok_or_else(|| EthApiError::HeaderNotFound(block_id))?;

self.spawn_blocking_io(move |eth_api| {
let state = eth_api
.provider()
.state_by_block_id(block.parent_hash().into())
.map_err(Self::Error::from_eth_err)?;

let mut db = State::builder()
.with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(state)))
.with_bal_builder()
.build();

let block_txs = block.transactions_recovered();
let mut executor = RpcNodeCore::evm_config(&eth_api)
.executor_for_block(&mut db, block.sealed_block())
.map_err(RethError::other)
.map_err(Self::Error::from_eth_err)?;

executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
executor.evm_mut().db_mut().bump_bal_index();

// replay all transactions prior to the targeted transaction
for block_tx in block_txs {
executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
executor.evm_mut().db_mut().bump_bal_index();
}

executor
.apply_post_execution_changes()
.map_err(|err| EthApiError::Internal(err.into()))?;

let bal = db.take_built_alloy_bal();
Ok(bal)
})
.await
}
}
}
11 changes: 9 additions & 2 deletions crates/rpc/rpc-eth-api/src/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//! [`EthApiServer`](crate::EthApiServer), is implemented for any type that implements
//! all the `Eth` traits, e.g. `reth_rpc::EthApi`.

pub mod bal;
pub mod block;
pub mod blocking_task;
pub mod call;
Expand All @@ -28,6 +29,7 @@ pub mod state;
pub mod trace;
pub mod transaction;

pub use bal::GetBlockAccessList;
pub use block::{EthBlocks, LoadBlock};
pub use blocking_task::SpawnBlocking;
pub use call::{Call, EthCall};
Expand All @@ -43,9 +45,12 @@ pub use transaction::{EthTransactions, LoadTransaction};
use crate::FullEthApiTypes;

/// Extension trait that bundles traits needed for tracing transactions.
pub trait TraceExt: LoadTransaction + LoadBlock + SpawnBlocking + Trace + Call {}
pub trait TraceExt:
LoadTransaction + LoadBlock + SpawnBlocking + Trace + Call + GetBlockAccessList
{
}

impl<T> TraceExt for T where T: LoadTransaction + LoadBlock + Trace + Call {}
impl<T> TraceExt for T where T: LoadTransaction + LoadBlock + Trace + Call + GetBlockAccessList {}

/// Helper trait to unify all `eth` rpc server building block traits, for simplicity.
///
Expand All @@ -60,6 +65,7 @@ pub trait FullEthApi:
+ EthFees
+ Trace
+ LoadReceipt
+ GetBlockAccessList
{
}

Expand All @@ -73,5 +79,6 @@ impl<T> FullEthApi for T where
+ EthFees
+ Trace
+ LoadReceipt
+ GetBlockAccessList
{
}
6 changes: 6 additions & 0 deletions crates/rpc/rpc-eth-types/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ pub enum EthApiError {
/// The underlying error object
error: jsonrpsee_types::ErrorObject<'static>,
},
/// Error thrown when trying to access block access list for blocks before Amsterdam
#[error("Block access list not available for pre-Amsterdam blocks")]
BlockAccessListNotAvailablePreAmsterdam,
/// Any other error
#[error("{0}")]
Other(Box<dyn ToRpcError>),
Expand Down Expand Up @@ -345,6 +348,9 @@ impl From<EthApiError> for jsonrpsee_types::error::ErrorObject<'static> {
error.data(),
)
}
EthApiError::BlockAccessListNotAvailablePreAmsterdam => {
rpc_error_with_code(4445, error.to_string())
}
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions crates/rpc/rpc/src/eth/helpers/bal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! Contains RPC handler implementations specific to block access lists.

use reth_rpc_convert::RpcConvert;
use reth_rpc_eth_api::{helpers::bal::GetBlockAccessList, FromEvmError, RpcNodeCore};
use reth_rpc_eth_types::EthApiError;

use crate::EthApi;

impl<N, Rpc> GetBlockAccessList for EthApi<N, Rpc>
where
N: RpcNodeCore,
EthApiError: FromEvmError<N::Evm>,
Rpc: RpcConvert<Primitives = N::Primitives, Error = EthApiError, Evm = N::Evm>,
{
}
1 change: 1 addition & 0 deletions crates/rpc/rpc/src/eth/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod signer;
pub mod sync_listener;
pub mod types;

mod bal;
mod block;
mod call;
mod fees;
Expand Down
Loading