Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
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
16 changes: 9 additions & 7 deletions crates/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ repository.workspace = true
homepage.workspace = true

[dependencies]
# Workspace
anyhow.workspace = true
tracing.workspace = true
# Workspace Alloy Dependencies
alloy-consensus.workspace = true
alloy-primitives = { workspace = true, features = ["rlp"] }
alloy-rlp = { workspace = true, features = ["derive"] }
alloy-eips.workspace = true
op-alloy-consensus.workspace = true
revm = { workspace = true, optional = true }
spin.workspace = true

# Other Workspace Dependencies
lru.workspace = true
spin.workspace = true
anyhow.workspace = true
tracing.workspace = true
async-trait.workspace = true
revm = { workspace = true, optional = true }

# Local
kona-primitives = { path = "../primitives", version = "0.0.1" }
Expand All @@ -37,7 +39,8 @@ serde = { version = "1.0.203", default-features = false, features = ["derive"],
# `online` feature dependencies
c-kzg = { version = "1.0.2", default-features = false, optional = true }
sha2 = { version = "0.10.8", default-features = false, optional = true }
alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", optional = true}
alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }
alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }
alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", optional = true }
alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }
serde_json = { version = "1.0.94", default-features = false, optional = true }
Expand All @@ -47,7 +50,6 @@ reqwest = { version = "0.12.4", default-features = false, optional = true }
alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }
tracing-subscriber = { version = "0.3.18", optional = true }
alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }
alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false, optional = true }

[dev-dependencies]
tokio = { version = "1.38", features = ["full"] }
Expand Down
50 changes: 23 additions & 27 deletions crates/derive/src/online/alloy_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@ use crate::{
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use alloy_consensus::{Header, Receipt, ReceiptWithBloom, TxEnvelope, TxType};
use alloy_primitives::{Bytes, B256, U64};
use alloy_provider::{Provider, ReqwestProvider};
use alloy_rlp::{Buf, Decodable};
use alloy_rpc_client::RpcClient;
use alloy_transport::TransportResult;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use core::num::NonZeroUsize;
use lru::LruCache;

// todo: once alloy revision is bumped, use defined ReqwestClient type.
/// A client using a [`reqwest`] HTTP transport.
pub type ReqwestClient = RpcClient<alloy_transport_http::Http<reqwest::Client>>;

const CACHE_SIZE: usize = 16;

/// The [AlloyChainProvider] is a concrete implementation of the [ChainProvider] trait, providing
Expand All @@ -33,7 +30,7 @@ const CACHE_SIZE: usize = 16;
#[derive(Debug, Clone)]
pub struct AlloyChainProvider {
/// The inner Ethereum JSON-RPC provider.
inner: ReqwestClient,
inner: ReqwestProvider,
/// `header_by_hash` LRU cache.
header_by_hash_cache: LruCache<B256, Header>,
/// `block_info_by_number` LRU cache.
Expand All @@ -46,7 +43,7 @@ pub struct AlloyChainProvider {

impl AlloyChainProvider {
/// Creates a new [AlloyChainProvider] with the given alloy provider.
pub fn new(inner: ReqwestClient) -> Self {
pub fn new(inner: ReqwestProvider) -> Self {
Self {
inner,
header_by_hash_cache: LruCache::new(NonZeroUsize::new(CACHE_SIZE).unwrap()),
Expand All @@ -60,7 +57,7 @@ impl AlloyChainProvider {

/// Creates a new [AlloyChainProvider] from the provided [reqwest::Url].
pub fn new_http(url: reqwest::Url) -> Self {
let inner = ReqwestClient::new_http(url);
let inner = ReqwestProvider::new_http(url);
Self::new(inner)
}
}
Expand All @@ -72,8 +69,9 @@ impl ChainProvider for AlloyChainProvider {
return Ok(header.clone());
}

let raw_header: Bytes =
self.inner.request("debug_getRawHeader", [hash]).await.map_err(|e| anyhow!(e))?;
let raw_header: TransportResult<Bytes> =
self.inner.raw_request("debug_getRawHeader".into(), [hash]).await;
let raw_header: Bytes = raw_header.map_err(|e| anyhow!(e))?;
Header::decode(&mut raw_header.as_ref()).map_err(|e| anyhow!(e))
}

Expand All @@ -82,11 +80,9 @@ impl ChainProvider for AlloyChainProvider {
return Ok(*block_info);
}

let raw_header: Bytes = self
.inner
.request("debug_getRawHeader", [U64::from(number)])
.await
.map_err(|e| anyhow!(e))?;
let raw_header: TransportResult<Bytes> =
self.inner.raw_request("debug_getRawHeader".into(), [U64::from(number)]).await;
let raw_header: Bytes = raw_header.map_err(|e| anyhow!(e))?;
let header = Header::decode(&mut raw_header.as_ref()).map_err(|e| anyhow!(e))?;

let block_info = BlockInfo {
Expand All @@ -104,8 +100,9 @@ impl ChainProvider for AlloyChainProvider {
return Ok(receipts.clone());
}

let raw_receipts: Vec<Bytes> =
self.inner.request("debug_getRawReceipts", [hash]).await.map_err(|e| anyhow!(e))?;
let raw_receipts: TransportResult<Vec<Bytes>> =
self.inner.raw_request("debug_getRawReceipts".into(), [hash]).await;
let raw_receipts: Vec<Bytes> = raw_receipts.map_err(|e| anyhow!(e))?;

let receipts = raw_receipts
.iter()
Expand Down Expand Up @@ -133,8 +130,9 @@ impl ChainProvider for AlloyChainProvider {
return Ok(block_info_and_txs.clone());
}

let raw_block: Bytes =
self.inner.request("debug_getRawBlock", [hash]).await.map_err(|e| anyhow!(e))?;
let raw_block: TransportResult<Bytes> =
self.inner.raw_request("debug_getRawBlock".into(), [hash]).await;
let raw_block: Bytes = raw_block.map_err(|e| anyhow!(e))?;
let block = Block::decode(&mut raw_block.as_ref()).map_err(|e| anyhow!(e))?;

let block_info = BlockInfo {
Expand All @@ -157,7 +155,7 @@ impl ChainProvider for AlloyChainProvider {
#[derive(Debug, Clone)]
pub struct AlloyL2ChainProvider {
/// The inner Ethereum JSON-RPC provider.
inner: ReqwestClient,
inner: ReqwestProvider,
/// The rollup configuration.
rollup_config: Arc<RollupConfig>,
/// `payload_by_number` LRU cache.
Expand All @@ -170,7 +168,7 @@ pub struct AlloyL2ChainProvider {

impl AlloyL2ChainProvider {
/// Creates a new [AlloyL2ChainProvider] with the given alloy provider and [RollupConfig].
pub fn new(inner: ReqwestClient, rollup_config: Arc<RollupConfig>) -> Self {
pub fn new(inner: ReqwestProvider, rollup_config: Arc<RollupConfig>) -> Self {
Self {
inner,
rollup_config,
Expand All @@ -182,7 +180,7 @@ impl AlloyL2ChainProvider {

/// Creates a new [AlloyL2ChainProvider] from the provided [reqwest::Url].
pub fn new_http(url: reqwest::Url, rollup_config: Arc<RollupConfig>) -> Self {
let inner = ReqwestClient::new_http(url);
let inner = ReqwestProvider::new_http(url);
Self::new(inner, rollup_config)
}
}
Expand All @@ -205,11 +203,9 @@ impl L2ChainProvider for AlloyL2ChainProvider {
return Ok(payload.clone());
}

let raw_block: Bytes = self
.inner
.request("debug_getRawBlock", [U64::from(number)])
.await
.map_err(|e| anyhow!(e))?;
let raw_block: TransportResult<Bytes> =
self.inner.raw_request("debug_getRawBlock".into(), [U64::from(number)]).await;
let raw_block: Bytes = raw_block.map_err(|e| anyhow!(e))?;
let block = OpBlock::decode(&mut raw_block.as_ref()).map_err(|e| anyhow!(e))?;
let payload_envelope: L2ExecutionPayloadEnvelope = block.into();

Expand Down
31 changes: 18 additions & 13 deletions crates/derive/src/online/beacon_client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! Contains an online implementation of the [BeaconClient] trait.

use crate::{
online::ReqwestClient,
types::{APIConfigResponse, APIGenesisResponse, APIGetBlobSidecarsResponse, IndexedBlobHash},
use crate::types::{
APIConfigResponse, APIGenesisResponse, APIGetBlobSidecarsResponse, IndexedBlobHash,
};
use alloc::{boxed::Box, string::String};
use alloy_provider::{Provider, ReqwestProvider};
use alloy_transport::TransportResult;
use async_trait::async_trait;

/// The node version engine api method.
Expand Down Expand Up @@ -46,34 +47,39 @@ pub trait BeaconClient {
#[derive(Debug, Clone)]
pub struct OnlineBeaconClient {
/// The inner Ethereum JSON-RPC provider.
inner: ReqwestClient,
inner: ReqwestProvider,
}

impl OnlineBeaconClient {
/// Creates a new instance of the [OnlineBeaconClient].
pub fn new(inner: ReqwestClient) -> Self {
pub fn new(inner: ReqwestProvider) -> Self {
Self { inner }
}

/// Creates a new [OnlineBeaconClient] from the provided [reqwest::Url].
pub fn new_http(url: reqwest::Url) -> Self {
let inner = ReqwestClient::new_http(url);
let inner = ReqwestProvider::new_http(url);
Self::new(inner)
}
}

#[async_trait]
impl BeaconClient for OnlineBeaconClient {
async fn node_version(&self) -> anyhow::Result<String> {
self.inner.request(VERSION_METHOD, ()).await.map_err(|e| anyhow::anyhow!(e))
let res: TransportResult<String> = self.inner.raw_request(VERSION_METHOD.into(), ()).await;
res.map_err(|e| anyhow::anyhow!(e))
}

async fn config_spec(&self) -> anyhow::Result<APIConfigResponse> {
self.inner.request(SPEC_METHOD, ()).await.map_err(|e| anyhow::anyhow!(e))
let res: TransportResult<APIConfigResponse> =
self.inner.raw_request(SPEC_METHOD.into(), ()).await;
res.map_err(|e| anyhow::anyhow!(e))
}

async fn beacon_genesis(&self) -> anyhow::Result<APIGenesisResponse> {
self.inner.request(GENESIS_METHOD, ()).await.map_err(|e| anyhow::anyhow!(e))
let res: TransportResult<APIGenesisResponse> =
self.inner.raw_request(GENESIS_METHOD.into(), ()).await;
res.map_err(|e| anyhow::anyhow!(e))
}

async fn beacon_blob_side_cars(
Expand All @@ -83,9 +89,8 @@ impl BeaconClient for OnlineBeaconClient {
hashes: &[IndexedBlobHash],
) -> anyhow::Result<APIGetBlobSidecarsResponse> {
let method = alloc::format!("{}{}", SIDECARS_METHOD_PREFIX, slot);
self.inner
.request(method, (fetch_all_sidecars, hashes))
.await
.map_err(|e| anyhow::anyhow!(e))
let res: TransportResult<APIGetBlobSidecarsResponse> =
self.inner.raw_request(method.into(), (fetch_all_sidecars, hashes)).await;
res.map_err(|e| anyhow::anyhow!(e))
}
}
2 changes: 1 addition & 1 deletion crates/derive/src/online/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mod beacon_client;
pub use beacon_client::{BeaconClient, OnlineBeaconClient};

mod alloy_providers;
pub use alloy_providers::{AlloyChainProvider, AlloyL2ChainProvider, ReqwestClient};
pub use alloy_providers::{AlloyChainProvider, AlloyL2ChainProvider};

mod blob_provider;
pub use blob_provider::{OnlineBlobProvider, SimpleSlotDerivation};