Skip to content

Commit

Permalink
Implement engine_getBlobsV1
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsproul committed May 23, 2024
1 parent db9c559 commit 67b36e5
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 12 deletions.
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.

2 changes: 1 addition & 1 deletion crates/node-core/src/args/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ impl RpcServerArgs {
pool: Pool,
network: Network,
executor: Tasks,
engine_api: EngineApi<Provider, EngineT>,
engine_api: EngineApi<Provider, EngineT, Pool>,
jwt_secret: JwtSecret,
evm_config: EvmConfig,
) -> Result<AuthServerHandle, RpcError>
Expand Down
1 change: 1 addition & 0 deletions crates/node/builder/src/launch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ where
ctx.chain_spec(),
beacon_engine_handle,
node_adapter.components.payload_builder().clone().into(),
node_adapter.components.pool().clone(),
Box::new(ctx.task_executor().clone()),
);
info!(target: "reth::cli", "Engine API handler initialized");
Expand Down
9 changes: 8 additions & 1 deletion crates/rpc/rpc-api/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use reth_rpc_types::{
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration,
},
state::StateOverride,
BlockOverrides, Filter, Log, RichBlock, SyncStatus, TransactionRequest,
BlobTransactionId, BlockOverrides, Filter, GetBlobsResponse, Log, RichBlock, SyncStatus,
TransactionRequest,
};

// NOTE: We can't use associated types in the `EngineApi` trait because of jsonrpsee, so we use a
Expand Down Expand Up @@ -157,6 +158,12 @@ pub trait EngineApi<Engine: EngineTypes> {
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/common.md#capabilities>
#[method(name = "exchangeCapabilities")]
async fn exchange_capabilities(&self, capabilities: Vec<String>) -> RpcResult<Vec<String>>;

#[method(name = "getBlobsV1")]
async fn get_blobs_v1(
&self,
transaction_ids: Vec<BlobTransactionId>,
) -> RpcResult<GetBlobsResponse>;
}

/// A subset of the ETH rpc interface: <https://ethereum.github.io/execution-apis/api-documentation/>
Expand Down
1 change: 1 addition & 0 deletions crates/rpc/rpc-engine-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ reth-payload-builder.workspace = true
reth-tasks.workspace = true
reth-rpc-types-compat.workspace = true
reth-engine-primitives.workspace = true
reth-transaction-pool.workspace = true

# async
tokio = { workspace = true, features = ["sync"] }
Expand Down
48 changes: 38 additions & 10 deletions crates/rpc/rpc-engine-api/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ use reth_payload_builder::PayloadStore;
use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Hardfork, B256, U64};
use reth_provider::{BlockReader, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_rpc_api::EngineApiServer;
use reth_rpc_types::engine::{
CancunPayloadFields, ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2,
ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated,
PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES,
use reth_rpc_types::{
engine::{
CancunPayloadFields, ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2,
ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState,
ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES,
},
BlobTransactionId, GetBlobsResponse,
};
use reth_rpc_types_compat::engine::payload::{
convert_payload_input_v2_to_payload, convert_to_payload_body_v1,
};
use reth_tasks::TaskSpawner;
use reth_transaction_pool::TransactionPool;
use std::{sync::Arc, time::Instant};
use tokio::sync::oneshot;
use tracing::{trace, warn};
Expand All @@ -31,11 +35,11 @@ const MAX_PAYLOAD_BODIES_LIMIT: u64 = 1024;

/// The Engine API implementation that grants the Consensus layer access to data and
/// functions in the Execution layer that are crucial for the consensus process.
pub struct EngineApi<Provider, EngineT: EngineTypes> {
inner: Arc<EngineApiInner<Provider, EngineT>>,
pub struct EngineApi<Provider, EngineT: EngineTypes, Pool> {
inner: Arc<EngineApiInner<Provider, EngineT, Pool>>,
}

struct EngineApiInner<Provider, EngineT: EngineTypes> {
struct EngineApiInner<Provider, EngineT: EngineTypes, Pool> {
/// The provider to interact with the chain.
provider: Provider,
/// Consensus configuration
Expand All @@ -48,19 +52,23 @@ struct EngineApiInner<Provider, EngineT: EngineTypes> {
task_spawner: Box<dyn TaskSpawner>,
/// The latency and response type metrics for engine api calls
metrics: EngineApiMetrics,
/// Transaction pool.
tx_pool: Pool,
}

impl<Provider, EngineT> EngineApi<Provider, EngineT>
impl<Provider, EngineT, Pool> EngineApi<Provider, EngineT, Pool>
where
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
EngineT: EngineTypes + 'static,
Pool: TransactionPool + 'static,
{
/// Create new instance of [EngineApi].
pub fn new(
provider: Provider,
chain_spec: Arc<ChainSpec>,
beacon_consensus: BeaconConsensusEngineHandle<EngineT>,
payload_store: PayloadStore<EngineT>,
tx_pool: Pool,
task_spawner: Box<dyn TaskSpawner>,
) -> Self {
let inner = Arc::new(EngineApiInner {
Expand All @@ -70,6 +78,7 @@ where
payload_store,
task_spawner,
metrics: EngineApiMetrics::default(),
tx_pool,
});
Self { inner }
}
Expand Down Expand Up @@ -537,10 +546,11 @@ where
}

#[async_trait]
impl<Provider, EngineT> EngineApiServer<EngineT> for EngineApi<Provider, EngineT>
impl<Provider, EngineT, Pool> EngineApiServer<EngineT> for EngineApi<Provider, EngineT, Pool>
where
Provider: HeaderProvider + BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
EngineT: EngineTypes + 'static,
Pool: TransactionPool + 'static,
{
/// Handler for `engine_newPayloadV1`
/// See also <https://github.com/ethereum/execution-apis/blob/3d627c95a4d3510a8187dd02e0250ecb4331d27e/src/engine/paris.md#engine_newpayloadv1>
Expand Down Expand Up @@ -755,9 +765,27 @@ where
async fn exchange_capabilities(&self, _capabilities: Vec<String>) -> RpcResult<Vec<String>> {
Ok(CAPABILITIES.into_iter().map(str::to_owned).collect())
}

async fn get_blobs_v1(
&self,
transaction_ids: Vec<BlobTransactionId>,
) -> RpcResult<GetBlobsResponse> {
let mut results = vec![];

for transaction_id in transaction_ids {
results.push(
self.inner
.tx_pool
.get_blob(transaction_id.tx_hash)
.map_err(|e| EngineApiError::Internal(Box::new(e)))?,
);
}

Ok(GetBlobsResponse { blobs: results })
}
}

impl<Provider, EngineT> std::fmt::Debug for EngineApi<Provider, EngineT>
impl<Provider, EngineT, Pool> std::fmt::Debug for EngineApi<Provider, EngineT, Pool>
where
EngineT: EngineTypes,
{
Expand Down
13 changes: 13 additions & 0 deletions crates/rpc/rpc-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ pub use mev::*;
pub use net::*;
pub use peer::*;
pub use rpc::*;

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
pub struct BlobTransactionId {
pub tx_hash: alloy_primitives::TxHash,
pub versioned_hashes: Vec<alloy_primitives::B256>,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct GetBlobsResponse {
pub blobs: Vec<Option<BlobTransactionSidecar>>,
}

0 comments on commit 67b36e5

Please sign in to comment.