diff --git a/Cargo.lock b/Cargo.lock index 251d68382e0..4e876737d47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3447,6 +3447,7 @@ dependencies = [ "reth-network-peers", "reth-node-builder", "reth-op", + "reth-optimism-flashblocks", "reth-optimism-forks", "reth-payload-builder", "reth-rpc-api", @@ -9324,6 +9325,7 @@ dependencies = [ "reth-errors", "reth-evm", "reth-execution-types", + "reth-optimism-evm", "reth-optimism-primitives", "reth-primitives-traits", "reth-revm", diff --git a/crates/optimism/flashblocks/Cargo.toml b/crates/optimism/flashblocks/Cargo.toml index 207427fe720..5f10fd2eb2e 100644 --- a/crates/optimism/flashblocks/Cargo.toml +++ b/crates/optimism/flashblocks/Cargo.toml @@ -13,6 +13,7 @@ workspace = true [dependencies] # reth reth-optimism-primitives = { workspace = true, features = ["serde"] } +reth-optimism-evm.workspace = true reth-chain-state = { workspace = true, features = ["serde"] } reth-primitives-traits = { workspace = true, features = ["serde"] } reth-execution-types = { workspace = true, features = ["serde"] } diff --git a/crates/optimism/flashblocks/src/app.rs b/crates/optimism/flashblocks/src/app.rs index cb17c7ebdb5..99165d462c4 100644 --- a/crates/optimism/flashblocks/src/app.rs +++ b/crates/optimism/flashblocks/src/app.rs @@ -1,4 +1,4 @@ -use crate::{FlashBlockService, FlashBlockWsStream}; +use crate::{ExecutionPayloadBaseV1, FlashBlockService, FlashBlockWsStream}; use futures_util::StreamExt; use reth_evm::ConfigureEvm; use reth_primitives_traits::{BlockTy, HeaderTy, NodePrimitives, ReceiptTy}; @@ -23,7 +23,10 @@ where N: NodePrimitives, EvmConfig: ConfigureEvm< Primitives = N, - NextBlockEnvCtx: BuildPendingEnv + Unpin + 'static, + NextBlockEnvCtx: BuildPendingEnv + + From + + Unpin + + 'static, > + 'static, Provider: StateProviderFactory + BlockReaderIdExt< @@ -35,7 +38,7 @@ where + 'static, { let stream = FlashBlockWsStream::new(ws_url); - let mut service = FlashBlockService::new(stream, evm_config, provider, ()); + let mut service = FlashBlockService::new(stream, evm_config, provider); let (tx, rx) = watch::channel(None); tokio::spawn(async move { diff --git a/crates/optimism/flashblocks/src/payload.rs b/crates/optimism/flashblocks/src/payload.rs index 5d7b0076c68..ba92b6a111b 100644 --- a/crates/optimism/flashblocks/src/payload.rs +++ b/crates/optimism/flashblocks/src/payload.rs @@ -1,6 +1,7 @@ use alloy_eips::eip4895::Withdrawal; use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; use alloy_rpc_types_engine::PayloadId; +use reth_optimism_evm::OpNextBlockEnvAttributes; use reth_optimism_primitives::OpReceipt; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -93,3 +94,16 @@ pub struct ExecutionPayloadFlashblockDeltaV1 { /// The withdrawals root of the block. pub withdrawals_root: B256, } + +impl From for OpNextBlockEnvAttributes { + fn from(value: ExecutionPayloadBaseV1) -> Self { + Self { + timestamp: value.timestamp, + suggested_fee_recipient: value.fee_recipient, + prev_randao: value.prev_randao, + gas_limit: value.gas_limit, + parent_beacon_block_root: Some(value.parent_beacon_block_root), + extra_data: value.extra_data, + } + } +} diff --git a/crates/optimism/flashblocks/src/service.rs b/crates/optimism/flashblocks/src/service.rs index e6cefaa6e2a..02b8bdb22a9 100644 --- a/crates/optimism/flashblocks/src/service.rs +++ b/crates/optimism/flashblocks/src/service.rs @@ -1,5 +1,6 @@ -use crate::FlashBlock; +use crate::{ExecutionPayloadBaseV1, FlashBlock}; use alloy_eips::{eip2718::WithEncoded, BlockNumberOrTag, Decodable2718}; +use eyre::OptionExt; use futures_util::{Stream, StreamExt}; use reth_chain_state::ExecutedBlock; use reth_errors::RethError; @@ -12,7 +13,6 @@ use reth_primitives_traits::{ AlloyBlockHeader, BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SignedTransaction, }; use reth_revm::{database::StateProviderDatabase, db::State}; -use reth_rpc_eth_api::helpers::pending_block::PendingEnvBuilder; use reth_rpc_eth_types::{EthApiError, PendingBlock}; use reth_storage_api::{BlockReaderIdExt, StateProviderFactory}; use std::{ @@ -31,20 +31,18 @@ pub struct FlashBlockService< S, EvmConfig: ConfigureEvm, Provider, - Builder, > { rx: S, current: Option>, blocks: Vec, evm_config: EvmConfig, provider: Provider, - builder: Builder, } impl< N: NodePrimitives, S, - EvmConfig: ConfigureEvm, + EvmConfig: ConfigureEvm + Unpin>, Provider: StateProviderFactory + BlockReaderIdExt< Header = HeaderTy, @@ -52,12 +50,11 @@ impl< Transaction = N::SignedTx, Receipt = ReceiptTy, >, - Builder: PendingEnvBuilder, - > FlashBlockService + > FlashBlockService { /// Constructs a new `FlashBlockService` that receives [`FlashBlock`]s from `rx` stream. - pub const fn new(rx: S, evm_config: EvmConfig, provider: Provider, builder: Builder) -> Self { - Self { rx, current: None, blocks: Vec::new(), evm_config, provider, builder } + pub const fn new(rx: S, evm_config: EvmConfig, provider: Provider) -> Self { + Self { rx, current: None, blocks: Vec::new(), evm_config, provider } } /// Adds the `block` into the collection. @@ -115,7 +112,11 @@ impl< .latest_header()? .ok_or(EthApiError::HeaderNotFound(BlockNumberOrTag::Latest.into()))?; - let latest_attrs = self.builder.pending_env_attributes(&latest)?; + let attrs = self + .blocks + .iter() + .find_map(|v| v.base.clone()) + .ok_or_eyre("Missing base flashblock")?; let state_provider = self.provider.history_by_block_hash(latest.hash())?; let state = StateProviderDatabase::new(&state_provider); @@ -123,7 +124,7 @@ impl< let mut builder = self .evm_config - .builder_for_next_block(&mut db, &latest, latest_attrs) + .builder_for_next_block(&mut db, &latest, attrs.into()) .map_err(RethError::other)?; builder.apply_pre_execution_changes()?; @@ -161,7 +162,7 @@ impl< impl< N: NodePrimitives, S: Stream> + Unpin, - EvmConfig: ConfigureEvm, + EvmConfig: ConfigureEvm + Unpin>, Provider: StateProviderFactory + BlockReaderIdExt< Header = HeaderTy, @@ -169,8 +170,7 @@ impl< Transaction = N::SignedTx, Receipt = ReceiptTy, > + Unpin, - Builder: PendingEnvBuilder, - > Stream for FlashBlockService + > Stream for FlashBlockService { type Item = eyre::Result>; diff --git a/crates/optimism/rpc/src/eth/mod.rs b/crates/optimism/rpc/src/eth/mod.rs index e5e27f103db..46c267dc239 100644 --- a/crates/optimism/rpc/src/eth/mod.rs +++ b/crates/optimism/rpc/src/eth/mod.rs @@ -20,7 +20,9 @@ use reqwest::Url; use reth_evm::ConfigureEvm; use reth_node_api::{FullNodeComponents, FullNodeTypes, HeaderTy}; use reth_node_builder::rpc::{EthApiBuilder, EthApiCtx}; -use reth_optimism_flashblocks::{launch_wss_flashblocks_service, FlashBlockRx}; +use reth_optimism_flashblocks::{ + launch_wss_flashblocks_service, ExecutionPayloadBaseV1, FlashBlockRx, +}; use reth_rpc::eth::{core::EthApiInner, DevSigner}; use reth_rpc_eth_api::{ helpers::{ @@ -390,7 +392,11 @@ impl OpEthApiBuilder { impl EthApiBuilder for OpEthApiBuilder where N: FullNodeComponents< - Evm: ConfigureEvm> + Unpin>, + Evm: ConfigureEvm< + NextBlockEnvCtx: BuildPendingEnv> + + From + + Unpin, + >, >, NetworkT: RpcTypes, OpRpcConvert: RpcConvert, diff --git a/examples/custom-node/Cargo.toml b/examples/custom-node/Cargo.toml index 5b340a0e493..a2f35687655 100644 --- a/examples/custom-node/Cargo.toml +++ b/examples/custom-node/Cargo.toml @@ -12,6 +12,7 @@ reth-codecs.workspace = true reth-network-peers.workspace = true reth-node-builder.workspace = true reth-optimism-forks.workspace = true +reth-optimism-flashblocks.workspace = true reth-db-api.workspace = true reth-op = { workspace = true, features = ["node", "pool", "rpc"] } reth-payload-builder.workspace = true diff --git a/examples/custom-node/src/evm/config.rs b/examples/custom-node/src/evm/config.rs index 0fbb9e893f6..7078342f1f9 100644 --- a/examples/custom-node/src/evm/config.rs +++ b/examples/custom-node/src/evm/config.rs @@ -23,6 +23,7 @@ use reth_op::{ node::{OpEvmConfig, OpNextBlockEnvAttributes, OpRethReceiptBuilder}, primitives::SignedTransaction, }; +use reth_optimism_flashblocks::ExecutionPayloadBaseV1; use reth_rpc_api::eth::helpers::pending_block::BuildPendingEnv; use std::sync::Arc; @@ -136,6 +137,12 @@ pub struct CustomNextBlockEnvAttributes { extension: u64, } +impl From for CustomNextBlockEnvAttributes { + fn from(value: ExecutionPayloadBaseV1) -> Self { + Self { inner: value.into(), extension: 0 } + } +} + impl BuildPendingEnv for CustomNextBlockEnvAttributes { fn build_pending_env(parent: &SealedHeader) -> Self { Self {