From 1d9050c242ee46a566bd78fa39e3188ab7b48c7a Mon Sep 17 00:00:00 2001 From: Rez Date: Thu, 23 Oct 2025 15:07:44 +1100 Subject: [PATCH 01/25] custom payload builder --- Cargo.lock | 6 ++ Cargo.toml | 13 +++ src/bin/bera-sequencer.rs | 138 +++++++++++++++++++++++++++++++ src/evm/mod.rs | 7 ++ src/lib.rs | 50 ++++++++++- src/node/evm/mod.rs | 21 +++-- src/node/mod.rs | 10 ++- src/sequencer/mod.rs | 7 ++ src/sequencer/payload_service.rs | 38 +++++++++ 9 files changed, 276 insertions(+), 14 deletions(-) create mode 100644 src/bin/bera-sequencer.rs create mode 100644 src/sequencer/mod.rs create mode 100644 src/sequencer/payload_service.rs diff --git a/Cargo.lock b/Cargo.lock index 5efaeb71..6211595b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1473,14 +1473,18 @@ dependencies = [ "reth-ethereum-primitives", "reth-evm", "reth-evm-ethereum", + "reth-network", "reth-network-peers", "reth-node-api", "reth-node-builder", "reth-node-core", "reth-node-ethereum", + "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", + "reth-primitives", "reth-primitives-traits", + "reth-provider", "reth-rpc", "reth-rpc-builder", "reth-rpc-convert", @@ -1488,6 +1492,7 @@ dependencies = [ "reth-rpc-eth-api", "reth-rpc-eth-types", "reth-transaction-pool", + "reth-trie", "revm-inspectors", "serde", "serde_json", @@ -8033,6 +8038,7 @@ version = "1.8.2" source = "git+https://github.com/paradigmxyz/reth?tag=v1.8.2#9c30bf7af5e0d45deaf5917375c9922c16654b28" dependencies = [ "alloy-consensus", + "c-kzg", "once_cell", "reth-ethereum-forks", "reth-ethereum-primitives", diff --git a/Cargo.toml b/Cargo.toml index e0bc7542..dcd2f0a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,14 @@ version = "1.1.1-rc.0" edition = "2024" license = "MIT OR Apache-2.0" +[[bin]] +name = "bera-reth" +path = "src/main.rs" + +[[bin]] +name = "bera-sequencer" +path = "src/bin/bera-sequencer.rs" + [dependencies] alloy-consensus = "1.0.37" alloy-eips = "1.0.37" @@ -54,8 +62,13 @@ reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-network = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-validator = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-convert = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs new file mode 100644 index 00000000..92e51c1f --- /dev/null +++ b/src/bin/bera-sequencer.rs @@ -0,0 +1,138 @@ +//! Berachain Sequencer Binary +//! +//! This binary runs bera-reth with a custom payload builder for sequencing. +//! +//! Usage: `cargo run --bin bera-sequencer -- node` + +#[global_allocator] +static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator(); + +use bera_reth::{ + chainspec::{BerachainChainSpec, BerachainChainSpecParser}, + consensus::{BerachainBeaconConsensus, BerachainConsensusBuilder}, + engine::BerachainEngineTypes, + evm::BerachainEvmFactory, + node::{ + BerachainAddOns, BerachainExecutorBuilder, BerachainNode, BerachainPoolBuilder, + evm::config::BerachainEvmConfig, + }, + primitives::{BerachainHeader, BerachainPrimitives}, + sequencer::SequencerPayloadServiceBuilder, + transaction::BerachainTxEnvelope, + version::init_bera_version, +}; +use clap::Parser; +use reth::{CliRunner, api::BlockTy}; +use reth_cli_commands::node::NoArgs; +use reth_engine_local::LocalPayloadAttributesBuilder; +use reth_ethereum_cli::Cli; +use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; +use reth_node_builder::{ + DebugNode, Node, NodeAdapter, NodeComponentsBuilder, NodeHandle, WithLaunchContext, + components::ComponentsBuilder, +}; +use reth_node_ethereum::node::EthereumNetworkBuilder; +use reth_payload_primitives::{PayloadAttributesBuilder, PayloadTypes}; +use reth_provider::EthStorage; +use std::sync::Arc; +use tracing::info; + +/// Custom sequencer node type +#[derive(Debug, Clone, Default)] +pub struct SequencerNode; + +impl NodeTypes for SequencerNode { + type Primitives = BerachainPrimitives; + type ChainSpec = BerachainChainSpec; + type Storage = EthStorage; + type Payload = BerachainEngineTypes; +} + +impl Node for SequencerNode +where + N: FullNodeTypes, +{ + type ComponentsBuilder = ComponentsBuilder< + N, + BerachainPoolBuilder, + SequencerPayloadServiceBuilder, + EthereumNetworkBuilder, + BerachainExecutorBuilder, + BerachainConsensusBuilder, + >; + + type AddOns = BerachainAddOns< + NodeAdapter>::Components>, + bera_reth::rpc::BerachainEthApiBuilder, + bera_reth::engine::validator::BerachainEngineValidatorBuilder, + >; + + fn components_builder(&self) -> Self::ComponentsBuilder { + ComponentsBuilder::default() + .node_types() + .pool(BerachainPoolBuilder) + .executor(BerachainExecutorBuilder) + .payload(SequencerPayloadServiceBuilder::default()) + .network(EthereumNetworkBuilder::default()) + .consensus(BerachainConsensusBuilder) + } + + fn add_ons(&self) -> Self::AddOns { + BerachainAddOns::default() + } +} + +impl DebugNode for SequencerNode +where + N: FullNodeComponents, +{ + type RpcBlock = alloy_rpc_types::Block; + + fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> BlockTy { + rpc_block.into_consensus_block().convert_transactions() + } + + fn local_payload_attributes_builder( + chain_spec: &Self::ChainSpec, + ) -> impl PayloadAttributesBuilder<<::Payload as PayloadTypes>::PayloadAttributes> + { + LocalPayloadAttributesBuilder::new(Arc::new(chain_spec.clone())) + } +} + +fn main() { + // Install signal handler for better crash reporting + reth_cli_util::sigsegv_handler::install(); + + // Initialize Bera-Reth version metadata + init_bera_version().expect("Failed to initialize Bera-Reth version metadata"); + + // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided. + if std::env::var_os("RUST_BACKTRACE").is_none() { + unsafe { std::env::set_var("RUST_BACKTRACE", "1") }; + } + + let cli_components_builder = |spec: Arc| { + ( + BerachainEvmConfig::new_with_evm_factory(spec.clone(), BerachainEvmFactory::default()), + Arc::new(BerachainBeaconConsensus::new(spec)), + ) + }; + + if let Err(err) = Cli::::parse() + .with_runner_and_components::( + CliRunner::try_default_runtime().expect("Failed to create default runtime"), + cli_components_builder, + async move |builder, _| { + info!(target: "reth::cli", "Launching Berachain Sequencer node"); + let NodeHandle { node: _node, node_exit_future } = + builder.node(SequencerNode::default()).launch_with_debug_capabilities().await?; + + node_exit_future.await + }, + ) + { + eprintln!("Error: {err:?}"); + std::process::exit(1); + } +} diff --git a/src/evm/mod.rs b/src/evm/mod.rs index 2b820cff..60b1d031 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -271,6 +271,13 @@ where #[non_exhaustive] pub struct BerachainEvmFactory; +impl BerachainEvmFactory { + /// Creates a new instance of `BerachainEvmFactory`. + pub const fn new() -> Self { + Self + } +} + impl EvmFactory for BerachainEvmFactory { type Evm>> = BerachainEvm; diff --git a/src/lib.rs b/src/lib.rs index 30b4118d..9eeed075 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,8 +12,54 @@ pub mod node; pub mod pool; pub mod primitives; pub mod rpc; +pub mod sequencer; +#[cfg(test)] +pub mod test_utils; pub mod transaction; pub mod version; -#[cfg(test)] -pub mod test_utils; +// // Re-export reth crates +pub use reth::{self, *}; +pub use reth_basic_payload_builder as basic_payload_builder; +pub use reth_chainspec; +pub use reth_cli as cli; +pub use reth_cli_commands as cli_commands; +pub use reth_cli_util as cli_util; +pub use reth_codecs as codecs; +pub use reth_consensus_common as consensus_common; +pub use reth_db as db; +pub use reth_db_api as db_api; +pub use reth_engine_local as engine_local; +pub use reth_engine_primitives as engine_primitives; +pub use reth_errors as errors; +pub use reth_ethereum_cli as ethereum_cli; +pub use reth_ethereum_engine_primitives as ethereum_engine_primitives; +pub use reth_ethereum_payload_builder as ethereum_payload_builder; +pub use reth_ethereum_primitives as ethereum_primitives; +pub use reth_evm; +pub use reth_evm_ethereum as evm_ethereum; +pub use reth_network_peers as network_peers; +pub use reth_node_api as node_api; +pub use reth_node_builder as node_builder; +pub use reth_node_core as node_core; +pub use reth_node_ethereum as node_ethereum; +pub use reth_payload_builder; +pub use reth_payload_primitives as payload_primitives; +pub use reth_payload_validator as payload_validator; +pub use reth_primitives_traits as primitives_traits; +pub use reth_rpc; +pub use reth_rpc_convert as rpc_convert; +pub use reth_rpc_engine_api as rpc_engine_api; +pub use reth_rpc_eth_api as rpc_eth_api; +pub use reth_rpc_eth_types as rpc_eth_types; +pub use reth_transaction_pool as transaction_pool; +// +// // Re-export alloy crates +// pub use alloy_evm; +// pub use { +// alloy_consensus, alloy_eips, alloy_genesis, +// alloy_network, alloy_primitives, alloy_rlp, +// alloy_rpc_types, alloy_rpc_types_eth, +// alloy_serde, alloy_signer_local, +// alloy_sol_macro, alloy_sol_types, +// }; diff --git a/src/node/evm/mod.rs b/src/node/evm/mod.rs index 465d9263..dd848598 100644 --- a/src/node/evm/mod.rs +++ b/src/node/evm/mod.rs @@ -1,17 +1,17 @@ //! Berachain EVM executor using standard Ethereum execution with Berachain chain spec mod assembler; -mod block_context; +pub mod block_context; pub mod config; pub mod error; pub mod executor; pub mod receipt; -use crate::{ - evm::BerachainEvmFactory, - node::{BerachainNode, evm::config::BerachainEvmConfig}, -}; +pub use config::BerachainEvmConfig; + +use crate::evm; use alloy_primitives::Bytes; +use reth_node_api::NodeTypes; use reth_node_builder::{BuilderContext, FullNodeTypes, components::ExecutorBuilder}; /// Default extra data for Berachain blocks @@ -20,7 +20,7 @@ fn default_extra_data() -> String { } /// Default extra data in bytes for Berachain blocks -fn default_extra_data_bytes() -> Bytes { +pub fn default_extra_data_bytes() -> Bytes { Bytes::from(default_extra_data().as_bytes().to_vec()) } @@ -30,7 +30,12 @@ pub struct BerachainExecutorBuilder; impl ExecutorBuilder for BerachainExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes< + Types: NodeTypes< + ChainSpec = crate::chainspec::BerachainChainSpec, + Primitives = crate::primitives::BerachainPrimitives, + >, + >, { /// The EVM configuration type that will be built type EVM = BerachainEvmConfig; @@ -39,7 +44,7 @@ where async fn build_evm(self, ctx: &BuilderContext) -> eyre::Result { let evm_config = BerachainEvmConfig::new_with_evm_factory( ctx.chain_spec(), - BerachainEvmFactory::default(), + evm::BerachainEvmFactory::default(), ) .with_extra_data(default_extra_data_bytes()); Ok(evm_config) diff --git a/src/node/mod.rs b/src/node/mod.rs index 1b87f649..72f675bc 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -2,17 +2,19 @@ pub mod evm; +pub use crate::{ + consensus::BerachainConsensusBuilder, pool::BerachainPoolBuilder, rpc::BerachainAddOns, +}; +pub use evm::BerachainExecutorBuilder; + use crate::{ chainspec::BerachainChainSpec, - consensus::BerachainConsensusBuilder, engine::{ BerachainEngineTypes, builder::BerachainPayloadServiceBuilder, validator::BerachainEngineValidatorBuilder, }, - node::evm::BerachainExecutorBuilder, - pool::BerachainPoolBuilder, primitives::{BerachainHeader, BerachainPrimitives}, - rpc::{BerachainAddOns, BerachainEthApiBuilder}, + rpc::BerachainEthApiBuilder, transaction::BerachainTxEnvelope, }; use alloy_consensus::{SignableTransaction, error::ValueError}; diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs new file mode 100644 index 00000000..c81362e0 --- /dev/null +++ b/src/sequencer/mod.rs @@ -0,0 +1,7 @@ +//! Sequencer module for Berachain +//! +//! This module contains the custom payload builder for sequencing. + +pub mod payload_service; + +pub use payload_service::SequencerPayloadServiceBuilder; diff --git a/src/sequencer/payload_service.rs b/src/sequencer/payload_service.rs new file mode 100644 index 00000000..2242e987 --- /dev/null +++ b/src/sequencer/payload_service.rs @@ -0,0 +1,38 @@ +//! Custom payload service builder for the sequencer + +use crate::node::evm::BerachainEvmConfig; +use reth_node_api::{FullNodeTypes, NodeTypes}; +use reth_node_builder::{BuilderContext, components::PayloadServiceBuilder}; +use reth_payload_builder::{PayloadBuilderHandle, noop::NoopPayloadBuilderService}; +use reth_transaction_pool::TransactionPool; +use tracing::info; + +/// Custom payload service builder that spawns a NoopPayloadBuilder for now +#[derive(Debug, Clone, Default)] +pub struct SequencerPayloadServiceBuilder; + +impl PayloadServiceBuilder for SequencerPayloadServiceBuilder +where + N: FullNodeTypes, + Pool: TransactionPool + Unpin + 'static, +{ + async fn spawn_payload_builder_service( + self, + _ctx: &BuilderContext, + _pool: Pool, + _evm_config: BerachainEvmConfig, + ) -> eyre::Result::Payload>> { + info!(target: "sequencer", "Spawning sequencer payload service with NoopPayloadBuilder"); + + // For now, just spawn a NoopPayloadBuilder + let (noop_service, handle) = + NoopPayloadBuilderService::<::Payload>::new(); + + // Spawn the service + tokio::spawn(noop_service); + + info!(target: "sequencer", "Sequencer payload service started"); + + Ok(handle) + } +} From 65b7679a51658a47225b96637c7eee2546d0a4b4 Mon Sep 17 00:00:00 2001 From: Rez Date: Thu, 23 Oct 2025 15:11:53 +1100 Subject: [PATCH 02/25] shuffle things around --- src/bin/bera-sequencer.rs | 87 +++------------------------------------ src/sequencer/mod.rs | 2 + src/sequencer/node.rs | 83 +++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 82 deletions(-) create mode 100644 src/sequencer/node.rs diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 92e51c1f..edead50b 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -9,97 +9,20 @@ static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::ne use bera_reth::{ chainspec::{BerachainChainSpec, BerachainChainSpecParser}, - consensus::{BerachainBeaconConsensus, BerachainConsensusBuilder}, - engine::BerachainEngineTypes, + consensus::BerachainBeaconConsensus, evm::BerachainEvmFactory, - node::{ - BerachainAddOns, BerachainExecutorBuilder, BerachainNode, BerachainPoolBuilder, - evm::config::BerachainEvmConfig, - }, - primitives::{BerachainHeader, BerachainPrimitives}, - sequencer::SequencerPayloadServiceBuilder, - transaction::BerachainTxEnvelope, + node::evm::config::BerachainEvmConfig, + sequencer::SequencerNode, version::init_bera_version, }; use clap::Parser; -use reth::{CliRunner, api::BlockTy}; +use reth::CliRunner; use reth_cli_commands::node::NoArgs; -use reth_engine_local::LocalPayloadAttributesBuilder; use reth_ethereum_cli::Cli; -use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; -use reth_node_builder::{ - DebugNode, Node, NodeAdapter, NodeComponentsBuilder, NodeHandle, WithLaunchContext, - components::ComponentsBuilder, -}; -use reth_node_ethereum::node::EthereumNetworkBuilder; -use reth_payload_primitives::{PayloadAttributesBuilder, PayloadTypes}; -use reth_provider::EthStorage; +use reth_node_builder::NodeHandle; use std::sync::Arc; use tracing::info; -/// Custom sequencer node type -#[derive(Debug, Clone, Default)] -pub struct SequencerNode; - -impl NodeTypes for SequencerNode { - type Primitives = BerachainPrimitives; - type ChainSpec = BerachainChainSpec; - type Storage = EthStorage; - type Payload = BerachainEngineTypes; -} - -impl Node for SequencerNode -where - N: FullNodeTypes, -{ - type ComponentsBuilder = ComponentsBuilder< - N, - BerachainPoolBuilder, - SequencerPayloadServiceBuilder, - EthereumNetworkBuilder, - BerachainExecutorBuilder, - BerachainConsensusBuilder, - >; - - type AddOns = BerachainAddOns< - NodeAdapter>::Components>, - bera_reth::rpc::BerachainEthApiBuilder, - bera_reth::engine::validator::BerachainEngineValidatorBuilder, - >; - - fn components_builder(&self) -> Self::ComponentsBuilder { - ComponentsBuilder::default() - .node_types() - .pool(BerachainPoolBuilder) - .executor(BerachainExecutorBuilder) - .payload(SequencerPayloadServiceBuilder::default()) - .network(EthereumNetworkBuilder::default()) - .consensus(BerachainConsensusBuilder) - } - - fn add_ons(&self) -> Self::AddOns { - BerachainAddOns::default() - } -} - -impl DebugNode for SequencerNode -where - N: FullNodeComponents, -{ - type RpcBlock = alloy_rpc_types::Block; - - fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> BlockTy { - rpc_block.into_consensus_block().convert_transactions() - } - - fn local_payload_attributes_builder( - chain_spec: &Self::ChainSpec, - ) -> impl PayloadAttributesBuilder<<::Payload as PayloadTypes>::PayloadAttributes> - { - LocalPayloadAttributesBuilder::new(Arc::new(chain_spec.clone())) - } -} - fn main() { // Install signal handler for better crash reporting reth_cli_util::sigsegv_handler::install(); diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs index c81362e0..ec186119 100644 --- a/src/sequencer/mod.rs +++ b/src/sequencer/mod.rs @@ -2,6 +2,8 @@ //! //! This module contains the custom payload builder for sequencing. +pub mod node; pub mod payload_service; +pub use node::SequencerNode; pub use payload_service::SequencerPayloadServiceBuilder; diff --git a/src/sequencer/node.rs b/src/sequencer/node.rs new file mode 100644 index 00000000..11da8e32 --- /dev/null +++ b/src/sequencer/node.rs @@ -0,0 +1,83 @@ +use crate::{ + chainspec::BerachainChainSpec, + consensus::BerachainConsensusBuilder, + engine::BerachainEngineTypes, + node::{BerachainAddOns, BerachainExecutorBuilder, BerachainPoolBuilder}, + primitives::{BerachainHeader, BerachainPrimitives}, + rpc::BerachainEthApiBuilder, + sequencer::SequencerPayloadServiceBuilder, + transaction::BerachainTxEnvelope, +}; +use reth::api::BlockTy; +use reth_engine_local::LocalPayloadAttributesBuilder; +use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; +use reth_node_builder::{ + DebugNode, Node, NodeAdapter, NodeComponentsBuilder, components::ComponentsBuilder, +}; +use reth_node_ethereum::node::EthereumNetworkBuilder; +use reth_payload_primitives::{PayloadAttributesBuilder, PayloadTypes}; +use reth_provider::EthStorage; +use std::sync::Arc; + +/// Custom sequencer node type for Berachain +#[derive(Debug, Clone, Default)] +pub struct SequencerNode; + +impl NodeTypes for SequencerNode { + type Primitives = BerachainPrimitives; + type ChainSpec = BerachainChainSpec; + type Storage = EthStorage; + type Payload = BerachainEngineTypes; +} + +impl Node for SequencerNode +where + N: FullNodeTypes, +{ + type ComponentsBuilder = ComponentsBuilder< + N, + BerachainPoolBuilder, + SequencerPayloadServiceBuilder, + EthereumNetworkBuilder, + BerachainExecutorBuilder, + BerachainConsensusBuilder, + >; + + type AddOns = BerachainAddOns< + NodeAdapter>::Components>, + BerachainEthApiBuilder, + crate::engine::validator::BerachainEngineValidatorBuilder, + >; + + fn components_builder(&self) -> Self::ComponentsBuilder { + ComponentsBuilder::default() + .node_types() + .pool(BerachainPoolBuilder) + .executor(BerachainExecutorBuilder) + .payload(SequencerPayloadServiceBuilder::default()) + .network(EthereumNetworkBuilder::default()) + .consensus(BerachainConsensusBuilder) + } + + fn add_ons(&self) -> Self::AddOns { + BerachainAddOns::default() + } +} + +impl DebugNode for SequencerNode +where + N: FullNodeComponents, +{ + type RpcBlock = alloy_rpc_types::Block; + + fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> BlockTy { + rpc_block.into_consensus_block().convert_transactions() + } + + fn local_payload_attributes_builder( + chain_spec: &Self::ChainSpec, + ) -> impl PayloadAttributesBuilder<<::Payload as PayloadTypes>::PayloadAttributes> + { + LocalPayloadAttributesBuilder::new(Arc::new(chain_spec.clone())) + } +} From 5365056dc1faaf04faa75391df86952988747959 Mon Sep 17 00:00:00 2001 From: Rez Date: Fri, 24 Oct 2025 16:29:40 +1100 Subject: [PATCH 03/25] start minimal sequencer --- src/sequencer/minimal_payload_service.rs | 80 ++++++++++++++++++++++++ src/sequencer/mod.rs | 1 + src/sequencer/payload_service.rs | 21 ++++--- 3 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 src/sequencer/minimal_payload_service.rs diff --git a/src/sequencer/minimal_payload_service.rs b/src/sequencer/minimal_payload_service.rs new file mode 100644 index 00000000..7a8218fc --- /dev/null +++ b/src/sequencer/minimal_payload_service.rs @@ -0,0 +1,80 @@ +//! Minimal payload service that properly handles subscriptions + +use reth_payload_builder::{PayloadBuilderHandle, PayloadServiceCommand}; +use reth_payload_primitives::{PayloadBuilderAttributes, PayloadTypes}; +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; +use tokio::sync::{broadcast, mpsc}; +use tracing::info; + +/// A minimal payload builder service that handles subscriptions properly +pub struct MinimalPayloadService { + /// Receiver for commands + command_rx: mpsc::UnboundedReceiver>, + /// Event sender for subscriptions + events_tx: broadcast::Sender>, +} + +impl MinimalPayloadService +where + T: PayloadTypes, +{ + /// Creates a new minimal payload service with proper event handling + pub fn new() -> (Self, PayloadBuilderHandle) { + let (service_tx, command_rx) = mpsc::unbounded_channel(); + let (events_tx, _) = broadcast::channel(100); + + let service = Self { command_rx, events_tx }; + + let handle = PayloadBuilderHandle::new(service_tx); + (service, handle) + } +} + +impl Future for MinimalPayloadService +where + T: PayloadTypes, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + + loop { + match this.command_rx.poll_recv(cx) { + Poll::Ready(Some(cmd)) => match cmd { + PayloadServiceCommand::BuildNewPayload(attr, tx) => { + info!(target: "sequencer", "Received BuildNewPayload request"); + let id = attr.payload_id(); + let _ = tx.send(Ok(id)); + } + PayloadServiceCommand::BestPayload(_, tx) => { + info!(target: "sequencer", "Received BestPayload request"); + let _ = tx.send(None); + } + PayloadServiceCommand::PayloadTimestamp(_, tx) => { + info!(target: "sequencer", "Received PayloadTimestamp request"); + let _ = tx.send(None); + } + PayloadServiceCommand::Resolve(_, _, tx) => { + info!(target: "sequencer", "Received Resolve request"); + let _ = tx.send(None); + } + PayloadServiceCommand::Subscribe(tx) => { + info!(target: "sequencer", "Received Subscribe request - sending events receiver"); + let events_rx = this.events_tx.subscribe(); + let _ = tx.send(events_rx); + } + }, + Poll::Ready(None) => { + info!(target: "sequencer", "Payload service channel closed, shutting down"); + return Poll::Ready(()); + } + Poll::Pending => return Poll::Pending, + } + } + } +} diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs index ec186119..150414b5 100644 --- a/src/sequencer/mod.rs +++ b/src/sequencer/mod.rs @@ -2,6 +2,7 @@ //! //! This module contains the custom payload builder for sequencing. +pub mod minimal_payload_service; pub mod node; pub mod payload_service; diff --git a/src/sequencer/payload_service.rs b/src/sequencer/payload_service.rs index 2242e987..123b0412 100644 --- a/src/sequencer/payload_service.rs +++ b/src/sequencer/payload_service.rs @@ -1,9 +1,11 @@ //! Custom payload service builder for the sequencer -use crate::node::evm::BerachainEvmConfig; +use crate::{ + node::evm::BerachainEvmConfig, sequencer::minimal_payload_service::MinimalPayloadService, +}; use reth_node_api::{FullNodeTypes, NodeTypes}; use reth_node_builder::{BuilderContext, components::PayloadServiceBuilder}; -use reth_payload_builder::{PayloadBuilderHandle, noop::NoopPayloadBuilderService}; +use reth_payload_builder::PayloadBuilderHandle; use reth_transaction_pool::TransactionPool; use tracing::info; @@ -22,16 +24,15 @@ where _pool: Pool, _evm_config: BerachainEvmConfig, ) -> eyre::Result::Payload>> { - info!(target: "sequencer", "Spawning sequencer payload service with NoopPayloadBuilder"); + info!(target: "sequencer", "Spawning minimal sequencer payload service"); - // For now, just spawn a NoopPayloadBuilder - let (noop_service, handle) = - NoopPayloadBuilderService::<::Payload>::new(); + let (service, handle) = MinimalPayloadService::<::Payload>::new(); - // Spawn the service - tokio::spawn(noop_service); - - info!(target: "sequencer", "Sequencer payload service started"); + // Spawn the service to run indefinitely + tokio::spawn(async move { + service.await; + info!(target: "sequencer", "Payload service terminated"); + }); Ok(handle) } From dd75b49eb77e4516202e1c3ae941d50aca42e5f0 Mon Sep 17 00:00:00 2001 From: Rez Date: Tue, 28 Oct 2025 12:42:14 +1100 Subject: [PATCH 04/25] working sequencer Update rpc.rs progress-failing compile v1 Update payload_service.rs Update payload_service.rs Update payload_service.rs hmm Update payload_service.rs compiles but errs Update payload_service.rs working sequencer Update payload_service.rs --- Cargo.lock | 1 + Cargo.toml | 1 + src/engine/rpc.rs | 4 +- src/sequencer/minimal_payload_service.rs | 80 ----- src/sequencer/mod.rs | 4 +- src/sequencer/payload_service.rs | 367 +++++++++++++++++++++-- src/sequencer/payload_service_builder.rs | 66 ++++ 7 files changed, 410 insertions(+), 113 deletions(-) delete mode 100644 src/sequencer/minimal_payload_service.rs create mode 100644 src/sequencer/payload_service_builder.rs diff --git a/Cargo.lock b/Cargo.lock index 6211595b..4e479485 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1500,6 +1500,7 @@ dependencies = [ "test-fuzz", "thiserror 2.0.17", "tokio", + "tokio-util", "tracing", "vergen", "vergen-git2", diff --git a/Cargo.toml b/Cargo.toml index dcd2f0a2..6aa3e250 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1 serde = { version = "1.0", features = ["derive"], default-features = false } thiserror = "2.0" tokio = "1.46.0" +tokio-util = "0.7" tracing = "0.1.41" [dev-dependencies] diff --git a/src/engine/rpc.rs b/src/engine/rpc.rs index 9ed9b459..3a1dee6b 100644 --- a/src/engine/rpc.rs +++ b/src/engine/rpc.rs @@ -35,7 +35,7 @@ use reth_payload_primitives::{EngineObjectValidationError, PayloadAttributes, Pa use reth_rpc_engine_api::{EngineApi, EngineApiError, EngineCapabilities}; use reth_transaction_pool::TransactionPool; use std::sync::Arc; -use tracing::{debug, trace}; +use tracing::{debug, info, trace}; /// Builder for [`BerachainEngineApi`] implementation. #[derive(Debug, Default)] @@ -537,6 +537,7 @@ where attrs.timestamp(), attrs.prev_proposer_pubkey(), )?; + info!(target: "rpc::engine", "Serving engine_forkchoiceUpdatedV3P11 with attributes {:?}", attrs); } Ok(self.inner.fork_choice_updated_v3_metered(fork_choice_state, payload_attributes).await?) @@ -579,6 +580,7 @@ where payload_id: PayloadId, ) -> RpcResult { trace!(target: "rpc::engine", "Serving engine_getPayloadV4P11"); + info!(target: "rpc::engine", "Serving get_payload_v4_p11"); Ok(self.inner.get_payload_v4_metered(payload_id).await?) } diff --git a/src/sequencer/minimal_payload_service.rs b/src/sequencer/minimal_payload_service.rs deleted file mode 100644 index 7a8218fc..00000000 --- a/src/sequencer/minimal_payload_service.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! Minimal payload service that properly handles subscriptions - -use reth_payload_builder::{PayloadBuilderHandle, PayloadServiceCommand}; -use reth_payload_primitives::{PayloadBuilderAttributes, PayloadTypes}; -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll}, -}; -use tokio::sync::{broadcast, mpsc}; -use tracing::info; - -/// A minimal payload builder service that handles subscriptions properly -pub struct MinimalPayloadService { - /// Receiver for commands - command_rx: mpsc::UnboundedReceiver>, - /// Event sender for subscriptions - events_tx: broadcast::Sender>, -} - -impl MinimalPayloadService -where - T: PayloadTypes, -{ - /// Creates a new minimal payload service with proper event handling - pub fn new() -> (Self, PayloadBuilderHandle) { - let (service_tx, command_rx) = mpsc::unbounded_channel(); - let (events_tx, _) = broadcast::channel(100); - - let service = Self { command_rx, events_tx }; - - let handle = PayloadBuilderHandle::new(service_tx); - (service, handle) - } -} - -impl Future for MinimalPayloadService -where - T: PayloadTypes, -{ - type Output = (); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.get_mut(); - - loop { - match this.command_rx.poll_recv(cx) { - Poll::Ready(Some(cmd)) => match cmd { - PayloadServiceCommand::BuildNewPayload(attr, tx) => { - info!(target: "sequencer", "Received BuildNewPayload request"); - let id = attr.payload_id(); - let _ = tx.send(Ok(id)); - } - PayloadServiceCommand::BestPayload(_, tx) => { - info!(target: "sequencer", "Received BestPayload request"); - let _ = tx.send(None); - } - PayloadServiceCommand::PayloadTimestamp(_, tx) => { - info!(target: "sequencer", "Received PayloadTimestamp request"); - let _ = tx.send(None); - } - PayloadServiceCommand::Resolve(_, _, tx) => { - info!(target: "sequencer", "Received Resolve request"); - let _ = tx.send(None); - } - PayloadServiceCommand::Subscribe(tx) => { - info!(target: "sequencer", "Received Subscribe request - sending events receiver"); - let events_rx = this.events_tx.subscribe(); - let _ = tx.send(events_rx); - } - }, - Poll::Ready(None) => { - info!(target: "sequencer", "Payload service channel closed, shutting down"); - return Poll::Ready(()); - } - Poll::Pending => return Poll::Pending, - } - } - } -} diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs index 150414b5..474465e3 100644 --- a/src/sequencer/mod.rs +++ b/src/sequencer/mod.rs @@ -2,9 +2,9 @@ //! //! This module contains the custom payload builder for sequencing. -pub mod minimal_payload_service; pub mod node; pub mod payload_service; +pub mod payload_service_builder; pub use node::SequencerNode; -pub use payload_service::SequencerPayloadServiceBuilder; +pub use payload_service_builder::SequencerPayloadServiceBuilder; diff --git a/src/sequencer/payload_service.rs b/src/sequencer/payload_service.rs index 123b0412..421ceb49 100644 --- a/src/sequencer/payload_service.rs +++ b/src/sequencer/payload_service.rs @@ -1,39 +1,346 @@ -//! Custom payload service builder for the sequencer +//! Minimal payload service that properly handles subscriptions use crate::{ - node::evm::BerachainEvmConfig, sequencer::minimal_payload_service::MinimalPayloadService, + chainspec::BerachainChainSpec, + engine::{ + BerachainEngineTypes, + builder::default_berachain_payload, + payload::{BerachainBuiltPayload, BerachainPayloadBuilderAttributes}, + }, + node::evm::BerachainEvmConfig, + primitives::BerachainHeader, + transaction::BerachainTxEnvelope, }; -use reth_node_api::{FullNodeTypes, NodeTypes}; -use reth_node_builder::{BuilderContext, components::PayloadServiceBuilder}; -use reth_payload_builder::PayloadBuilderHandle; -use reth_transaction_pool::TransactionPool; -use tracing::info; +use alloy_primitives::B256; +use reth::{payload::PayloadId, providers::BlockReaderIdExt}; +use reth_basic_payload_builder::{BuildArguments, BuildOutcome, PayloadConfig}; +use reth_chainspec::ChainSpecProvider; +use reth_ethereum_payload_builder::EthereumBuilderConfig; +use reth_payload_builder::{PayloadBuilderError, PayloadBuilderHandle, PayloadServiceCommand}; +use reth_payload_primitives::PayloadBuilderAttributes; +use reth_provider::StateProviderFactory; +use reth_transaction_pool::{PoolTransaction, TransactionPool}; +use std::{ + future::Future, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; +use tokio::sync::{broadcast, mpsc, oneshot}; +use tokio_util::sync::CancellationToken; +use tracing::{error, info, warn}; + +/// State machine for the sequencer payload service. +/// +/// The sequencer follows a simple two-state pattern: +/// 1. `WaitingForForkchoiceUpdate`: Idle, waiting for a new payload build request +/// 2. `BuildingPayload`: Actively building a payload in a background task +/// +/// State transitions: +/// - `WaitingForForkchoiceUpdate` -> `BuildingPayload`: On `BuildNewPayload` command (fcu) +/// - `BuildingPayload` -> `WaitingForForkchoiceUpdate`: On `Resolve` command (getPayload) +/// +/// Only one payload can be built at a time to preserve pre-confirmations +pub enum SequencerStateMachine { + /// Waiting for a forkchoice update to trigger a new payload build. + /// This is the initial and idle state. + WaitingForForkchoiceUpdate, + /// Actively building a payload in a background blocking task. + /// The receiver is taken when the payload is resolved (getPayload). + BuildingPayload { + payload_id: PayloadId, + attributes: BerachainPayloadBuilderAttributes, + /// Receiver for the built payload - becomes None after resolution + receiver: Option>>, + /// Token to signal the build task to stop adding transactions and finalize + cancel_token: CancellationToken, + }, +} + +pub struct SequencerPayloadService { + status: SequencerStateMachine, + command_rx: mpsc::UnboundedReceiver>, + events_tx: broadcast::Sender>, + client: Client, + pool: Pool, + evm_config: BerachainEvmConfig, + builder_config: EthereumBuilderConfig, +} + +impl SequencerPayloadService +where + Client: StateProviderFactory + + ChainSpecProvider + + Clone + + 'static + + BlockReaderIdExt
, + Pool: TransactionPool> + 'static, +{ + /// Creates a new minimal payload service with proper event handling + pub fn new( + client: Client, + pool: Pool, + evm_config: BerachainEvmConfig, + builder_config: EthereumBuilderConfig, + ) -> (Self, PayloadBuilderHandle) { + let (service_tx, command_rx) = mpsc::unbounded_channel(); + let (events_tx, _) = broadcast::channel(100); + + let service = Self { + command_rx, + events_tx, + status: SequencerStateMachine::WaitingForForkchoiceUpdate, + client, + pool, + evm_config, + builder_config, + }; + + let handle = PayloadBuilderHandle::new(service_tx); + (service, handle) + } + + /// Processes commands and manages state transitions. + /// + /// Command handling by state: + /// - `WaitingForForkchoiceUpdate`: + /// - `Subscribe`: Returns event receiver for payload notifications + /// - `BuildNewPayload`: Spawns build task, transitions to BuildingPayload + /// - `BuildingPayload`: + /// - `PayloadTimestamp`: Returns timestamp from stored attributes + /// - `Resolve`: Cancels build, waits for result, transitions to WaitingForForkchoiceUpdate + fn transition(&mut self, cmd: PayloadServiceCommand) { + match &mut self.status { + SequencerStateMachine::WaitingForForkchoiceUpdate => match cmd { + PayloadServiceCommand::Subscribe(tx) => { + info!(target: "sequencer", "Received Subscribe request - sending events receiver"); + let events_rx = self.events_tx.subscribe(); + let _ = tx.send(events_rx); + } + PayloadServiceCommand::BuildNewPayload(attr, tx) => { + info!(target: "sequencer", "Received BuildNewPayload request"); + let id = attr.payload_id(); + + info!(target: "sequencer", payload_id = ?id, "Starting async payload build"); + + // Create cancellation token and oneshot channel for the build + let cancel_token = CancellationToken::new(); + let (build_tx, build_rx) = oneshot::channel(); + + // Clone data for the blocking task + let client = self.client.clone(); + let pool = self.pool.clone(); + let evm_config = self.evm_config.clone(); + let builder_config = self.builder_config.clone(); + let cancel = cancel_token.clone(); + let attr_clone = attr.clone(); + + // Spawn a blocking task for CPU-intensive payload building + tokio::task::spawn_blocking(move || { + info!(target: "sequencer", payload_id = ?id, "Payload build blocking task started"); + + // Execute the CPU-intensive build synchronously + let result = Self::build_payload_blocking( + client, + pool, + evm_config, + builder_config, + attr_clone, + cancel, + ); + + match result { + Ok(payload) => { + info!(target: "sequencer", payload_id = ?id, "Payload build completed successfully"); + let _ = build_tx.send(Ok(payload)); + } + Err(err) => { + error!(target: "sequencer", payload_id = ?id, ?err, "Payload build failed"); + let _ = build_tx.send(Err(err)); + } + } + }); + + // Transition to building state + info!(target: "sequencer", payload_id = ?id, "Transitioning to BuildingPayload state"); + self.status = SequencerStateMachine::BuildingPayload { + payload_id: id, + attributes: attr, + receiver: Some(build_rx), + cancel_token, + }; + + // Immediately respond with the payload ID + let _ = tx.send(Ok(id)); + } + cmd => { + warn!(target: "sequencer", ?cmd, "Received unexpected PayloadServiceCommand while waiting for forkchoice update"); + } + }, + SequencerStateMachine::BuildingPayload { + payload_id, + attributes, + receiver, + cancel_token, + } => match cmd { + PayloadServiceCommand::PayloadTimestamp(id, tx) => { + info!(target: "sequencer", "Received PayloadTimestamp request for payload {}", id); -/// Custom payload service builder that spawns a NoopPayloadBuilder for now -#[derive(Debug, Clone, Default)] -pub struct SequencerPayloadServiceBuilder; + let timestamp = + if id == *payload_id { Some(Ok(attributes.timestamp)) } else { None }; -impl PayloadServiceBuilder for SequencerPayloadServiceBuilder + let _ = tx.send(timestamp); + } + PayloadServiceCommand::Resolve(id, _kind, tx) => { + info!(target: "sequencer", payload_id = ?id, "Received Resolve request for payload"); + + if id != *payload_id { + warn!(target: "sequencer", payload_id = ?id, current_id = ?payload_id, "Resolve request for different payload ID"); + let _ = tx.send(None); + return; + } + + if let Some(receiver) = receiver.take() { + info!(target: "sequencer", payload_id = ?payload_id, "Signaling build task to complete"); + cancel_token.cancel(); + + info!(target: "sequencer", payload_id = ?payload_id, "Waiting for build task to complete"); + + let result = tokio::task::block_in_place(|| { + tokio::runtime::Handle::current().block_on(receiver) + }); + + let response = match result { + Ok(Ok(payload)) => { + info!(target: "sequencer", payload_id = ?payload_id, "Payload successfully retrieved"); + Some(Box::pin(async move { Ok(payload) }) as _) + } + Ok(Err(err)) => { + error!(target: "sequencer", payload_id = ?payload_id, ?err, "Payload build failed"); + Some(Box::pin(async move { Err(err) }) as _) + } + Err(_) => { + warn!(target: "sequencer", payload_id = ?payload_id, "Build task dropped without result"); + None + } + }; + + let _ = tx.send(response); + + self.status = SequencerStateMachine::WaitingForForkchoiceUpdate; + info!(target: "sequencer", "Transitioned to WaitingForForkchoiceUpdate state"); + } else { + warn!(target: "sequencer", payload_id = ?payload_id, "Payload already resolved"); + let _ = tx.send(None); + } + } + cmd => { + warn!(target: "sequencer", ?cmd, "Received unexpected PayloadServiceCommand while BuildingPayload"); + } + }, + } + } + + fn build_payload_blocking( + client: Client, + pool: Pool, + evm_config: BerachainEvmConfig, + builder_config: EthereumBuilderConfig, + attributes: BerachainPayloadBuilderAttributes, + _cancel_token: CancellationToken, + ) -> Result { + let payload_id = attributes.id; + info!(target: "sequencer", payload_id = ?payload_id, parent = ?attributes.parent, timestamp = attributes.timestamp, "Beginning payload construction"); + + let parent_header = if attributes.parent().is_zero() { + // Use latest header for genesis block case + client + .latest_header() + .map_err(PayloadBuilderError::from)? + .ok_or_else(|| PayloadBuilderError::MissingParentHeader(B256::ZERO))? + } else { + // Fetch specific header by hash + client + .sealed_header_by_hash(attributes.parent()) + .map_err(PayloadBuilderError::from)? + .ok_or_else(|| PayloadBuilderError::MissingParentHeader(attributes.parent()))? + }; + + info!(target: "sequencer", payload_id = ?payload_id, parent_number = parent_header.number, "Retrieved parent block"); + + // Create the payload config + let config = PayloadConfig::new(Arc::new(parent_header.clone()), attributes.clone()); + + // TODO: The cancel token should be passed to default_berachain_payload and checked + // after each transaction is processed. When cancelled, it should stop processing + // more transactions and immediately finalize the block with transactions processed so far. + // This will enable getPayload to signal "stop adding txs and return what you have". + // For now, we don't pass the cancel token to avoid complexity. + let args = BuildArguments::new( + Default::default(), // cached_reads + config, + Default::default(), // cancel token - TODO: integrate with our cancel_token + None, // best_payload + ); + + info!(target: "sequencer", payload_id = ?payload_id, "Calling default_berachain_payload to build block"); + + // Build the payload using the standard function + let outcome = default_berachain_payload( + evm_config, + client.clone(), + pool.clone(), + builder_config, + args, + |attrs| pool.best_transactions_with_attributes(attrs), + )?; + + // Return the built payload + match outcome { + BuildOutcome::Better { payload, .. } => { + let block_number = payload.block.header().number; + let tx_count = payload.block.body().transactions.len(); + info!(target: "sequencer", + payload_id = ?payload_id, + block_number = block_number, + tx_count = tx_count, + "Successfully built payload" + ); + Ok(payload) + } + _ => { + warn!(target: "sequencer", payload_id = ?payload_id, "Build did not produce a better payload"); + panic!("cannot happen as payloads will always be better"); + } + } + } +} + +impl Future for SequencerPayloadService where - N: FullNodeTypes, - Pool: TransactionPool + Unpin + 'static, + Client: StateProviderFactory + + ChainSpecProvider + + Clone + + 'static + + BlockReaderIdExt
+ + Unpin, + Pool: TransactionPool> + + Unpin + + 'static, { - async fn spawn_payload_builder_service( - self, - _ctx: &BuilderContext, - _pool: Pool, - _evm_config: BerachainEvmConfig, - ) -> eyre::Result::Payload>> { - info!(target: "sequencer", "Spawning minimal sequencer payload service"); - - let (service, handle) = MinimalPayloadService::<::Payload>::new(); - - // Spawn the service to run indefinitely - tokio::spawn(async move { - service.await; - info!(target: "sequencer", "Payload service terminated"); - }); - - Ok(handle) + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + loop { + match this.command_rx.poll_recv(cx) { + Poll::Ready(Some(cmd)) => this.transition(cmd), + Poll::Ready(None) => { + info!(target: "sequencer", "Payload service channel closed, shutting down"); + return Poll::Ready(()); + } + Poll::Pending => return Poll::Pending, + } + } } } diff --git a/src/sequencer/payload_service_builder.rs b/src/sequencer/payload_service_builder.rs new file mode 100644 index 00000000..5ec52668 --- /dev/null +++ b/src/sequencer/payload_service_builder.rs @@ -0,0 +1,66 @@ +//! Custom payload service builder for the sequencer + +use crate::{ + engine::BerachainEngineTypes, node::evm::BerachainEvmConfig, + sequencer::payload_service::SequencerPayloadService, +}; +use reth::chainspec::EthChainSpec; +use reth_node_api::FullNodeTypes; +use reth_node_builder::{BuilderContext, PayloadBuilderConfig, components::PayloadServiceBuilder}; +use reth_payload_builder::PayloadBuilderHandle; +use reth_transaction_pool::{PoolTransaction, TransactionPool}; +use tracing::info; + +/// Custom payload service builder that spawns a NoopPayloadBuilder for now +#[derive(Debug, Clone, Default)] +pub struct SequencerPayloadServiceBuilder; + +impl PayloadServiceBuilder for SequencerPayloadServiceBuilder +where + N: FullNodeTypes< + Types: reth_node_api::NodeTypes< + Payload = BerachainEngineTypes, + ChainSpec = crate::chainspec::BerachainChainSpec, + Primitives = crate::primitives::BerachainPrimitives, + >, + >, + N::Provider: reth_provider::StateProviderFactory + + reth_chainspec::ChainSpecProvider + + reth_provider::BlockReader + + Clone + + Unpin + + 'static, + Pool: TransactionPool< + Transaction: PoolTransaction, + > + Unpin + + Clone + + 'static, +{ + async fn spawn_payload_builder_service( + self, + ctx: &BuilderContext, + pool: Pool, + evm_config: BerachainEvmConfig, + ) -> eyre::Result::Payload>> { + info!(target: "sequencer", "Spawning minimal sequencer payload service"); + + // Get configuration + let conf = ctx.payload_builder_config(); + let chain = ctx.chain_spec().chain(); + let gas_limit = conf.gas_limit_for(chain); + + let builder_config = + reth_ethereum_payload_builder::EthereumBuilderConfig::new().with_gas_limit(gas_limit); + + let (service, handle) = + SequencerPayloadService::new(ctx.provider().clone(), pool, evm_config, builder_config); + + // Spawn the service to run indefinitely + tokio::spawn(async move { + service.await; + info!(target: "sequencer", "Payload service terminated"); + }); + + Ok(handle) + } +} From f278e1ad9aab73e5d7a5f56e755c94be78d635d5 Mon Sep 17 00:00:00 2001 From: Rez Date: Wed, 29 Oct 2025 19:11:58 +1100 Subject: [PATCH 05/25] tidy --- src/evm/mod.rs | 7 ------- src/lib.rs | 46 ---------------------------------------------- 2 files changed, 53 deletions(-) diff --git a/src/evm/mod.rs b/src/evm/mod.rs index 60b1d031..2b820cff 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -271,13 +271,6 @@ where #[non_exhaustive] pub struct BerachainEvmFactory; -impl BerachainEvmFactory { - /// Creates a new instance of `BerachainEvmFactory`. - pub const fn new() -> Self { - Self - } -} - impl EvmFactory for BerachainEvmFactory { type Evm>> = BerachainEvm; diff --git a/src/lib.rs b/src/lib.rs index 9eeed075..d84b93fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,49 +17,3 @@ pub mod sequencer; pub mod test_utils; pub mod transaction; pub mod version; - -// // Re-export reth crates -pub use reth::{self, *}; -pub use reth_basic_payload_builder as basic_payload_builder; -pub use reth_chainspec; -pub use reth_cli as cli; -pub use reth_cli_commands as cli_commands; -pub use reth_cli_util as cli_util; -pub use reth_codecs as codecs; -pub use reth_consensus_common as consensus_common; -pub use reth_db as db; -pub use reth_db_api as db_api; -pub use reth_engine_local as engine_local; -pub use reth_engine_primitives as engine_primitives; -pub use reth_errors as errors; -pub use reth_ethereum_cli as ethereum_cli; -pub use reth_ethereum_engine_primitives as ethereum_engine_primitives; -pub use reth_ethereum_payload_builder as ethereum_payload_builder; -pub use reth_ethereum_primitives as ethereum_primitives; -pub use reth_evm; -pub use reth_evm_ethereum as evm_ethereum; -pub use reth_network_peers as network_peers; -pub use reth_node_api as node_api; -pub use reth_node_builder as node_builder; -pub use reth_node_core as node_core; -pub use reth_node_ethereum as node_ethereum; -pub use reth_payload_builder; -pub use reth_payload_primitives as payload_primitives; -pub use reth_payload_validator as payload_validator; -pub use reth_primitives_traits as primitives_traits; -pub use reth_rpc; -pub use reth_rpc_convert as rpc_convert; -pub use reth_rpc_engine_api as rpc_engine_api; -pub use reth_rpc_eth_api as rpc_eth_api; -pub use reth_rpc_eth_types as rpc_eth_types; -pub use reth_transaction_pool as transaction_pool; -// -// // Re-export alloy crates -// pub use alloy_evm; -// pub use { -// alloy_consensus, alloy_eips, alloy_genesis, -// alloy_network, alloy_primitives, alloy_rlp, -// alloy_rpc_types, alloy_rpc_types_eth, -// alloy_serde, alloy_signer_local, -// alloy_sol_macro, alloy_sol_types, -// }; From b1eb55ef70dc4c76addb0f17809d8204efdc3682 Mon Sep 17 00:00:00 2001 From: Rez Date: Wed, 29 Oct 2025 19:12:37 +1100 Subject: [PATCH 06/25] Update rpc.rs --- src/engine/rpc.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine/rpc.rs b/src/engine/rpc.rs index 3a1dee6b..733b7b7a 100644 --- a/src/engine/rpc.rs +++ b/src/engine/rpc.rs @@ -537,7 +537,6 @@ where attrs.timestamp(), attrs.prev_proposer_pubkey(), )?; - info!(target: "rpc::engine", "Serving engine_forkchoiceUpdatedV3P11 with attributes {:?}", attrs); } Ok(self.inner.fork_choice_updated_v3_metered(fork_choice_state, payload_attributes).await?) @@ -580,7 +579,6 @@ where payload_id: PayloadId, ) -> RpcResult { trace!(target: "rpc::engine", "Serving engine_getPayloadV4P11"); - info!(target: "rpc::engine", "Serving get_payload_v4_p11"); Ok(self.inner.get_payload_v4_metered(payload_id).await?) } From b72ed49576e29e2d71375c152792e6990addaf7b Mon Sep 17 00:00:00 2001 From: Rez Date: Wed, 29 Oct 2025 19:19:28 +1100 Subject: [PATCH 07/25] Update Cargo.toml --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6aa3e250..e7caf2c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,25 +57,25 @@ reth-ethereum-payload-builder = { git = "https://github.com/paradigmxyz/reth", t reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-network = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-network = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-validator = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-convert = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-engine-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } +reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } serde = { version = "1.0", features = ["derive"], default-features = false } thiserror = "2.0" tokio = "1.46.0" From 17559de3c44c110886c59e0195dc2925c9f08ed9 Mon Sep 17 00:00:00 2001 From: Rez Date: Wed, 29 Oct 2025 19:21:25 +1100 Subject: [PATCH 08/25] lint --- src/engine/rpc.rs | 2 +- src/sequencer/node.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/rpc.rs b/src/engine/rpc.rs index 733b7b7a..9ed9b459 100644 --- a/src/engine/rpc.rs +++ b/src/engine/rpc.rs @@ -35,7 +35,7 @@ use reth_payload_primitives::{EngineObjectValidationError, PayloadAttributes, Pa use reth_rpc_engine_api::{EngineApi, EngineApiError, EngineCapabilities}; use reth_transaction_pool::TransactionPool; use std::sync::Arc; -use tracing::{debug, info, trace}; +use tracing::{debug, trace}; /// Builder for [`BerachainEngineApi`] implementation. #[derive(Debug, Default)] diff --git a/src/sequencer/node.rs b/src/sequencer/node.rs index 11da8e32..fcadf7b6 100644 --- a/src/sequencer/node.rs +++ b/src/sequencer/node.rs @@ -54,7 +54,7 @@ where .node_types() .pool(BerachainPoolBuilder) .executor(BerachainExecutorBuilder) - .payload(SequencerPayloadServiceBuilder::default()) + .payload(SequencerPayloadServiceBuilder) .network(EthereumNetworkBuilder::default()) .consensus(BerachainConsensusBuilder) } From ec2a6eaeff525c66ba204ea90dae76327f365e77 Mon Sep 17 00:00:00 2001 From: Rez Date: Wed, 29 Oct 2025 19:26:12 +1100 Subject: [PATCH 09/25] make pr fixes --- Cargo.lock | 137 +------------------------------ Cargo.toml | 6 -- src/bin/bera-sequencer.rs | 2 +- src/sequencer/payload_service.rs | 14 +--- 4 files changed, 9 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e479485..527ff506 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1434,9 +1434,7 @@ dependencies = [ "alloy-genesis", "alloy-network", "alloy-primitives", - "alloy-provider", "alloy-rlp", - "alloy-rpc-client", "alloy-rpc-types", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -1473,7 +1471,6 @@ dependencies = [ "reth-ethereum-primitives", "reth-evm", "reth-evm-ethereum", - "reth-network", "reth-network-peers", "reth-node-api", "reth-node-builder", @@ -1482,17 +1479,14 @@ dependencies = [ "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", - "reth-primitives", "reth-primitives-traits", "reth-provider", "reth-rpc", - "reth-rpc-builder", "reth-rpc-convert", "reth-rpc-engine-api", "reth-rpc-eth-api", "reth-rpc-eth-types", "reth-transaction-pool", - "reth-trie", "revm-inspectors", "serde", "serde_json", @@ -2270,16 +2264,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -3200,21 +3184,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -3774,22 +3743,6 @@ dependencies = [ "webpki-roots 1.0.3", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.17" @@ -5098,23 +5051,6 @@ dependencies = [ "unsigned-varint", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nom" version = "7.1.3" @@ -5374,50 +5310,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", -] - [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-sys" -version = "0.9.110" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -6236,11 +6134,9 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -6252,7 +6148,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -8039,7 +7934,6 @@ version = "1.8.2" source = "git+https://github.com/paradigmxyz/reth?tag=v1.8.2#9c30bf7af5e0d45deaf5917375c9922c16654b28" dependencies = [ "alloy-consensus", - "c-kzg", "once_cell", "reth-ethereum-forks", "reth-ethereum-primitives", @@ -9383,7 +9277,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -9402,7 +9296,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "jni", "log", @@ -9411,7 +9305,7 @@ dependencies = [ "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.5.1", + "security-framework", "security-framework-sys", "webpki-root-certs 0.26.11", "windows-sys 0.59.0", @@ -9579,19 +9473,6 @@ dependencies = [ "cc", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.5.1" @@ -9599,7 +9480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ "bitflags 2.9.4", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -10431,16 +10312,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" diff --git a/Cargo.toml b/Cargo.toml index e7caf2c4..e973397f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,6 @@ reth-ethereum-payload-builder = { git = "https://github.com/paradigmxyz/reth", t reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-network = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } @@ -66,7 +65,6 @@ reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8. reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-validator = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } @@ -75,7 +73,6 @@ reth-rpc-engine-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8 reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } serde = { version = "1.0", features = ["derive"], default-features = false } thiserror = "2.0" tokio = "1.46.0" @@ -83,12 +80,9 @@ tokio-util = "0.7" tracing = "0.1.41" [dev-dependencies] -alloy-provider = "1.0.37" -alloy-rpc-client = "1.0.37" alloy-rpc-types-trace = "1.0.37" eyre = "0.6.12" reth-e2e-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-rpc-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } revm-inspectors = "0.30.0" serde_json = "1.0" test-fuzz = "7" diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index edead50b..85952b2d 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -49,7 +49,7 @@ fn main() { async move |builder, _| { info!(target: "reth::cli", "Launching Berachain Sequencer node"); let NodeHandle { node: _node, node_exit_future } = - builder.node(SequencerNode::default()).launch_with_debug_capabilities().await?; + builder.node(SequencerNode).launch_with_debug_capabilities().await?; node_exit_future.await }, diff --git a/src/sequencer/payload_service.rs b/src/sequencer/payload_service.rs index 421ceb49..54db6346 100644 --- a/src/sequencer/payload_service.rs +++ b/src/sequencer/payload_service.rs @@ -49,7 +49,7 @@ pub enum SequencerStateMachine { /// The receiver is taken when the payload is resolved (getPayload). BuildingPayload { payload_id: PayloadId, - attributes: BerachainPayloadBuilderAttributes, + timestamp: u64, /// Receiver for the built payload - becomes None after resolution receiver: Option>>, /// Token to signal the build task to stop adding transactions and finalize @@ -161,11 +161,9 @@ where } }); - // Transition to building state - info!(target: "sequencer", payload_id = ?id, "Transitioning to BuildingPayload state"); self.status = SequencerStateMachine::BuildingPayload { payload_id: id, - attributes: attr, + timestamp: attr.timestamp, receiver: Some(build_rx), cancel_token, }; @@ -179,16 +177,12 @@ where }, SequencerStateMachine::BuildingPayload { payload_id, - attributes, + timestamp, receiver, cancel_token, } => match cmd { PayloadServiceCommand::PayloadTimestamp(id, tx) => { - info!(target: "sequencer", "Received PayloadTimestamp request for payload {}", id); - - let timestamp = - if id == *payload_id { Some(Ok(attributes.timestamp)) } else { None }; - + let timestamp = if id == *payload_id { Some(Ok(*timestamp)) } else { None }; let _ = tx.send(timestamp); } PayloadServiceCommand::Resolve(id, _kind, tx) => { From f6a1e545fd9f10e7bd7071bf8626595c3d8c84ed Mon Sep 17 00:00:00 2001 From: Rez Date: Sun, 23 Nov 2025 06:26:41 +1100 Subject: [PATCH 10/25] Update Cargo.lock --- Cargo.lock | 136 +++-------------------------------------------------- 1 file changed, 7 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47da0f5b..e6053b93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1447,9 +1447,7 @@ dependencies = [ "alloy-genesis", "alloy-network", "alloy-primitives", - "alloy-provider", "alloy-rlp", - "alloy-rpc-client", "alloy-rpc-types", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -1491,11 +1489,12 @@ dependencies = [ "reth-node-builder", "reth-node-core", "reth-node-ethereum", + "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", "reth-primitives-traits", + "reth-provider", "reth-rpc", - "reth-rpc-builder", "reth-rpc-convert", "reth-rpc-engine-api", "reth-rpc-eth-api", @@ -1508,6 +1507,7 @@ dependencies = [ "test-fuzz", "thiserror 2.0.16", "tokio", + "tokio-util", "tracing", "vergen", "vergen-git2", @@ -2272,16 +2272,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -3196,21 +3186,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -3784,22 +3759,6 @@ dependencies = [ "webpki-roots 1.0.2", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.16" @@ -5120,23 +5079,6 @@ dependencies = [ "unsigned-varint", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nom" version = "7.1.3" @@ -5405,50 +5347,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", -] - [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -6236,11 +6140,9 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -6252,7 +6154,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -9393,7 +9294,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.4.0", + "security-framework", ] [[package]] @@ -9412,7 +9313,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "jni", "log", @@ -9421,7 +9322,7 @@ dependencies = [ "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.4.0", + "security-framework", "security-framework-sys", "webpki-root-certs 0.26.11", "windows-sys 0.59.0", @@ -9595,19 +9496,6 @@ dependencies = [ "cc", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.4.0" @@ -9615,7 +9503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" dependencies = [ "bitflags 2.9.4", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -10442,16 +10330,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.2" From 590a01e55024b9f965918bb13e69b6bb77bf2d71 Mon Sep 17 00:00:00 2001 From: Rez Date: Sun, 23 Nov 2025 10:47:18 +1100 Subject: [PATCH 11/25] v1 --- Cargo.lock | 149 ++++++++++++++++++++++++++++++ Cargo.toml | 3 + src/lib.rs | 1 + src/rblib_integration/limits.rs | 19 ++++ src/rblib_integration/mod.rs | 5 + src/rblib_integration/platform.rs | 74 +++++++++++++++ 6 files changed, 251 insertions(+) create mode 100644 src/rblib_integration/limits.rs create mode 100644 src/rblib_integration/mod.rs create mode 100644 src/rblib_integration/platform.rs diff --git a/Cargo.lock b/Cargo.lock index e6053b93..2a695b9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,29 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae62e633fa48b4190af5e841eb05179841bb8b713945103291e2c0867037c0d1" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-trie", +] + [[package]] name = "alloy-chains" version = "0.2.9" @@ -150,6 +173,41 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-contract" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630288cf4f3a34a8c6bc75c03dce1dbd47833138f65f37d53a1661eafc96b83f" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "serde_json", + "thiserror 2.0.16", +] + +[[package]] +name = "alloy-core" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe6c56d58fbfa9f0f6299376e8ce33091fc6494239466814c3f54b55743cb09" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + [[package]] name = "alloy-dyn-abi" version = "1.3.1" @@ -503,6 +561,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", "alloy-rpc-types-eth", + "alloy-rpc-types-mev", "alloy-serde", "serde", ] @@ -723,6 +782,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b74e91b0b553c115d14bd0ed41898309356dc85d0e3d4b9014c4e7715e48c8ad" dependencies = [ + "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck", @@ -741,12 +801,14 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84194d31220803f5f62d0a00f583fd3a062b36382e2bea446f1af96727754565" dependencies = [ + "alloy-json-abi", "const-hex", "dunce", "heck", "macro-string", "proc-macro2", "quote", + "serde_json", "syn 2.0.106", "syn-solidity", ] @@ -1464,6 +1526,7 @@ dependencies = [ "jsonrpsee-core", "jsonrpsee-proc-macros", "modular-bitfield", + "rblib", "reth", "reth-basic-payload-builder", "reth-chainspec", @@ -5562,6 +5625,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pipelines-macros" +version = "0.3.1" +source = "git+https://github.com/flashbots/rblib#f4abbf12883e4486d6a3898d8b00613dec444618" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -6028,6 +6102,43 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rblib" +version = "0.3.1" +source = "git+https://github.com/flashbots/rblib#f4abbf12883e4486d6a3898d8b00613dec444618" +dependencies = [ + "alloy", + "alloy-evm", + "alloy-serde", + "dashmap 6.1.0", + "derive_more", + "eyre", + "futures", + "itertools 0.14.0", + "jsonrpsee", + "metrics", + "parking_lot", + "pipelines-macros", + "reth", + "reth-basic-payload-builder", + "reth-cli", + "reth-errors", + "reth-ethereum", + "reth-ethereum-payload-builder", + "reth-evm", + "reth-node-builder", + "reth-payload-builder", + "reth-rpc-api", + "reth-transaction-pool", + "serde", + "smallvec", + "thiserror 2.0.16", + "tokio", + "tokio-stream", + "tracing", + "uuid", +] + [[package]] name = "recvmsg" version = "1.0.0" @@ -7069,6 +7180,44 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "reth-ethereum" +version = "1.8.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.8.2#9c30bf7af5e0d45deaf5917375c9922c16654b28" +dependencies = [ + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "reth-chainspec", + "reth-codecs", + "reth-consensus", + "reth-consensus-common", + "reth-db", + "reth-engine-local", + "reth-eth-wire", + "reth-ethereum-consensus", + "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", + "reth-network", + "reth-network-api", + "reth-node-api", + "reth-node-builder", + "reth-node-core", + "reth-node-ethereum", + "reth-primitives-traits", + "reth-provider", + "reth-revm", + "reth-rpc", + "reth-rpc-api", + "reth-rpc-builder", + "reth-rpc-eth-types", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "reth-trie", + "reth-trie-db", +] + [[package]] name = "reth-ethereum-cli" version = "1.8.2" diff --git a/Cargo.toml b/Cargo.toml index 2f736afb..99afca13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,9 @@ derive_more = "2.0.1" eyre = "0.6.12" sha2 = "0.10" +# rblib for advanced block building +rblib = { git = "https://github.com/flashbots/rblib", version = "0.3.1", default-features = false } + # rpc jsonrpsee = "0.26.0" jsonrpsee-core = { version = "0.26.0", features = ["server"] } diff --git a/src/lib.rs b/src/lib.rs index d84b93fc..0eeaa683 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub mod hardforks; pub mod node; pub mod pool; pub mod primitives; +pub mod rblib_integration; pub mod rpc; pub mod sequencer; #[cfg(test)] diff --git a/src/rblib_integration/limits.rs b/src/rblib_integration/limits.rs new file mode 100644 index 00000000..4fc09b59 --- /dev/null +++ b/src/rblib_integration/limits.rs @@ -0,0 +1,19 @@ +use rblib::prelude::*; +use std::time::Duration; + +use super::platform::BerachainPlatform; + +/// Default limits for Berachain payload building +#[derive(Debug, Clone, Default)] +pub struct BerachainLimits; + +impl PlatformLimits for BerachainLimits { + fn create(&self, _block: &BlockContext) -> Limits { + Limits { + gas_limit: 30_000_000, // TODO: calculate correctly + blob_params: None, // TODO: Get blob configuration from chainspec + max_transactions: Some(1_000), + deadline: Some(Duration::from_secs(2)), // bera block time + } + } +} diff --git a/src/rblib_integration/mod.rs b/src/rblib_integration/mod.rs new file mode 100644 index 00000000..cc9244ce --- /dev/null +++ b/src/rblib_integration/mod.rs @@ -0,0 +1,5 @@ +pub mod limits; +pub mod platform; + +pub use limits::BerachainLimits; +pub use platform::BerachainPlatform; diff --git a/src/rblib_integration/platform.rs b/src/rblib_integration/platform.rs new file mode 100644 index 00000000..be7c8bec --- /dev/null +++ b/src/rblib_integration/platform.rs @@ -0,0 +1,74 @@ +use super::limits::BerachainLimits; +use crate::{ + chainspec::BerachainChainSpec, + engine::{BerachainEngineTypes, payload::BerachainPayloadBuilderAttributes}, + node::{BerachainNode, evm::config::BerachainEvmConfig}, + pool::transaction::BerachainPooledTransaction, + primitives::BerachainHeader, +}; +use alloy_eips::eip1559::ETHEREUM_BLOCK_GAS_LIMIT_36M; +use rblib::prelude::*; +use reth::api::PayloadTypes; +use std::sync::Arc; + +/// Platform implementation for Berachain +/// +/// This type implements rblib's Platform trait for Berachain, +/// allowing the use of rblib's advanced block building capabilities. +#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct BerachainPlatform; + +impl Platform for BerachainPlatform { + type NodeTypes = BerachainNode; + type EvmConfig = BerachainEvmConfig; + type PooledTransaction = BerachainPooledTransaction; + type Bundle = FlashbotsBundle; + type DefaultLimits = BerachainLimits; + + fn evm_config

(chainspec: Arc) -> BerachainEvmConfig + where + P: traits::PlatformExecBounds, + { + // Create EVM config with the Berachain chain spec + use crate::evm::BerachainEvmFactory; + BerachainEvmConfig::new_with_evm_factory(chainspec, BerachainEvmFactory::default()) + } + + fn next_block_environment_context

( + _chainspec: &BerachainChainSpec, + parent: &BerachainHeader, + attributes: &BerachainPayloadBuilderAttributes, + ) -> ::NextBlockEnvCtx + where + P: traits::PlatformExecBounds, + { + use crate::node::evm::config::BerachainNextBlockEnvAttributes; + + BerachainNextBlockEnvAttributes { + timestamp: attributes.timestamp, + suggested_fee_recipient: attributes.suggested_fee_recipient, + prev_randao: attributes.prev_randao, + gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_36M, /* TODO: Get from config, e.g. + * ETHEREUM_BLOCK_GAS_LIMIT_36M */ + parent_beacon_block_root: attributes.parent_beacon_block_root, + withdrawals: Some(attributes.withdrawals.clone()), + prev_proposer_pubkey: attributes.prev_proposer_pubkey.clone(), + } + } + + fn build_payload

( + _checkpoint: Checkpoint

, + _provider: &dyn reth::providers::StateProvider, + ) -> Result<::BuiltPayload, PayloadBuilderError> + where + P: traits::PlatformExecBounds, + { + // For now, return an error indicating this is not yet implemented + // A proper implementation would extract state from the checkpoint + // and build a BerachainBuiltPayload + Err(PayloadBuilderError::Other(Box::new(std::io::Error::new( + std::io::ErrorKind::Other, + "BerachainPlatform payload building not yet fully implemented", + )))) + } +} From 242a3057bbfcd11f1647cf28fb3ed2fecb736f8d Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 09:06:42 +1100 Subject: [PATCH 12/25] progress --- Cargo.toml | 1 - src/rblib_integration/platform.rs | 343 ++++++++++++++++++++++++++++-- src/rpc/api.rs | 26 ++- 3 files changed, 352 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 99afca13..51aa9197 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ derive_more = "2.0.1" eyre = "0.6.12" sha2 = "0.10" -# rblib for advanced block building rblib = { git = "https://github.com/flashbots/rblib", version = "0.3.1", default-features = false } # rpc diff --git a/src/rblib_integration/platform.rs b/src/rblib_integration/platform.rs index be7c8bec..e4b049fe 100644 --- a/src/rblib_integration/platform.rs +++ b/src/rblib_integration/platform.rs @@ -1,15 +1,58 @@ use super::limits::BerachainLimits; use crate::{ chainspec::BerachainChainSpec, - engine::{BerachainEngineTypes, payload::BerachainPayloadBuilderAttributes}, - node::{BerachainNode, evm::config::BerachainEvmConfig}, + engine::{ + BerachainEngineTypes, + builder::default_berachain_payload, + payload::{BerachainBuiltPayload, BerachainPayloadBuilderAttributes}, + }, + hardforks::BerachainHardforks, + node::{ + BerachainNode, + evm::config::{BerachainEvmConfig, BerachainNextBlockEnvAttributes}, + }, pool::transaction::BerachainPooledTransaction, primitives::BerachainHeader, + transaction::BerachainTxEnvelope, +}; +use alloy_consensus::Transaction; +use alloy_eips::eip1559::{ETHEREUM_BLOCK_GAS_LIMIT, ETHEREUM_BLOCK_GAS_LIMIT_30M}; +use alloy_primitives::U256; +use alloy_rlp::Encodable; +use rblib::{ + alloy::evm::{ + Evm, + revm::{context::Block, database::State}, + }, + prelude::*, + reth::{ + errors::{BlockExecutionError, BlockValidationError, ConsensusError}, + ethereum::{ + chainspec::EthereumHardforks, + evm::revm::database::StateProviderDatabase, + provider::{StateProvider, StateProviderFactory}, + }, + }, }; -use alloy_eips::eip1559::ETHEREUM_BLOCK_GAS_LIMIT_36M; -use rblib::prelude::*; use reth::api::PayloadTypes; +use reth_basic_payload_builder::{BuildArguments, BuildOutcome, PayloadConfig, is_better_payload}; +use reth_chainspec::{ChainSpecProvider, EthChainSpec}; +use reth_consensus_common::validation::MAX_RLP_BLOCK_SIZE; +use reth_ethereum_engine_primitives::BlobSidecars; +use reth_ethereum_payload_builder::EthereumBuilderConfig; +use reth_evm::{ + ConfigureEvm, + execute::{BlockBuilder, BlockBuilderOutcome}, +}; +use reth_payload_primitives::PayloadBuilderAttributes; +use reth_primitives_traits::transaction::error::InvalidTransactionError; +use reth_transaction_pool::{ + BestTransactionsAttributes, BestTransactionsFor, PoolTransaction, TransactionPool, + error::{Eip4844PoolTransactionError, InvalidPoolTransactionError}, + noop::NoopTransactionPool, +}; use std::sync::Arc; +use tracing::{debug, trace, warn}; /// Platform implementation for Berachain /// @@ -36,7 +79,7 @@ impl Platform for BerachainPlatform { fn next_block_environment_context

( _chainspec: &BerachainChainSpec, - parent: &BerachainHeader, + _parent: &BerachainHeader, attributes: &BerachainPayloadBuilderAttributes, ) -> ::NextBlockEnvCtx where @@ -48,8 +91,7 @@ impl Platform for BerachainPlatform { timestamp: attributes.timestamp, suggested_fee_recipient: attributes.suggested_fee_recipient, prev_randao: attributes.prev_randao, - gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_36M, /* TODO: Get from config, e.g. - * ETHEREUM_BLOCK_GAS_LIMIT_36M */ + gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_30M, // TODO: Get from config parent_beacon_block_root: attributes.parent_beacon_block_root, withdrawals: Some(attributes.withdrawals.clone()), prev_proposer_pubkey: attributes.prev_proposer_pubkey.clone(), @@ -57,18 +99,287 @@ impl Platform for BerachainPlatform { } fn build_payload

( - _checkpoint: Checkpoint

, - _provider: &dyn reth::providers::StateProvider, + payload: Checkpoint

, + provider: &dyn StateProvider, ) -> Result<::BuiltPayload, PayloadBuilderError> where P: traits::PlatformExecBounds, { - // For now, return an error indicating this is not yet implemented - // A proper implementation would extract state from the checkpoint - // and build a BerachainBuiltPayload - Err(PayloadBuilderError::Other(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - "BerachainPlatform payload building not yet fully implemented", - )))) + let evm_config = payload.block().evm_config().clone(); + let chain_spec = payload.block().chainspec(); + + let payload_config = PayloadConfig::new( + Arc::new(payload.block().parent().clone()), + payload.block().attributes().clone(), + ); + + let build_args = + BuildArguments::new(Default::default(), payload_config, Default::default(), None); + + let builder_config = EthereumBuilderConfig::new(); + + // This will reorder transactions. Something we want to avoid for flashblocks. + let transactions = payload.history().transactions().cloned().collect(); + let transactions = Box::new(FixedTransactions::::new(transactions)); + + default_berachain_payload_for_platform( + evm_config, + chain_spec, + provider, + NoopTransactionPool::new(), + &builder_config, + build_args, + || self.pool.best_transactions_with_attributes(attributes), + )? + .into_payload() + .ok_or_else(|| PayloadBuilderError::MissingPayload) } } + +#[inline] +pub fn default_berachain_payload_for_platform( + evm_config: BerachainEvmConfig, + chain_spec: &Arc>, + state_provider: &dyn StateProvider, + pool: Pool, + builder_config: &EthereumBuilderConfig, + args: BuildArguments, + best_txs: F, +) -> Result, PayloadBuilderError> +where + Client: StateProviderFactory + ChainSpecProvider, + Pool: TransactionPool>, + F: FnOnce(BestTransactionsAttributes) -> BestTransactionsFor, +{ + let BuildArguments { mut cached_reads, config, cancel, best_payload } = args; + let PayloadConfig { parent_header, attributes } = config; + + let state = StateProviderDatabase::new(&state_provider); + let mut db = + State::builder().with_database(cached_reads.as_db_mut(state)).with_bundle_update().build(); + + let mut builder = evm_config + .builder_for_next_block( + &mut db, + &parent_header, + BerachainNextBlockEnvAttributes { + timestamp: attributes.timestamp(), + suggested_fee_recipient: attributes.suggested_fee_recipient(), + prev_randao: attributes.prev_randao(), + gas_limit: builder_config.gas_limit(parent_header.gas_limit), + parent_beacon_block_root: attributes.parent_beacon_block_root(), + withdrawals: Some(attributes.withdrawals().clone()), + prev_proposer_pubkey: attributes.prev_proposer_pubkey, + }, + ) + .map_err(PayloadBuilderError::other)?; + + // let chain_spec = client.chain_spec(); + + debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); + let mut cumulative_gas_used = 0; + let block_gas_limit: u64 = builder.evm_mut().block().gas_limit; + let base_fee = builder.evm_mut().block().basefee; + + let mut best_txs = best_txs(BestTransactionsAttributes::new( + base_fee, + builder.evm_mut().block().blob_gasprice().map(|gasprice| gasprice as u64), + )); + let mut total_fees = U256::ZERO; + + builder.apply_pre_execution_changes().map_err(|err| { + warn!(target: "payload_builder", %err, "failed to apply pre-execution changes"); + PayloadBuilderError::Internal(err.into()) + })?; + + // initialize empty blob sidecars at first. If cancun is active then this will be populated by + // blob sidecars if any. + let mut blob_sidecars = BlobSidecars::Empty; + + let mut block_blob_count = 0; + let mut block_transactions_rlp_length = 0; + + let blob_params = chain_spec.blob_params_at_timestamp(attributes.timestamp); + let max_blob_count = + blob_params.as_ref().map(|params| params.max_blob_count).unwrap_or_default(); + + let is_osaka = chain_spec.is_osaka_active_at_timestamp(attributes.timestamp); + + // Check if Prague3 is active and skip all transactions if so + if chain_spec.is_prague3_active_at_timestamp(attributes.timestamp()) { + warn!(target: "payload_builder", "Prague3 is active, building payload without transactions is not supported"); + return Err(PayloadBuilderError::Other(Box::from( + "Prague 3 block building is not supported", + ))) + } + // Skip all transactions and proceed to finalize the empty block + while let Some(pool_tx) = best_txs.next() { + // ensure we still have capacity for this transaction + if cumulative_gas_used + pool_tx.gas_limit() > block_gas_limit { + // we can't fit this transaction into the block, so we need to mark it as invalid + // which also removes all dependent transaction from the iterator before we can + // continue + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::ExceedsGasLimit(pool_tx.gas_limit(), block_gas_limit), + ); + continue + } + + // check if the job was cancelled, if so we can exit early + if cancel.is_cancelled() { + return Ok(BuildOutcome::Cancelled) + } + + // convert tx to a signed transaction + let tx = pool_tx.to_consensus(); + + let estimated_block_size_with_tx = block_transactions_rlp_length + + tx.inner().length() + + attributes.withdrawals().length() + + 1024; // 1Kb of overhead for the block header + + if is_osaka && estimated_block_size_with_tx > MAX_RLP_BLOCK_SIZE { + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::OversizedData( + estimated_block_size_with_tx, + MAX_RLP_BLOCK_SIZE, + ), + ); + continue; + } + + // There's only limited amount of blob space available per block, so we need to check if + // the EIP-4844 can still fit in the block + let mut blob_tx_sidecar = None; + if let Some(blob_tx) = tx.as_eip4844() { + let tx_blob_count = blob_tx.tx().blob_versioned_hashes.len() as u64; + + if block_blob_count + tx_blob_count > max_blob_count { + // we can't fit this _blob_ transaction into the block, so we mark it as + // invalid, which removes its dependent transactions from + // the iterator. This is similar to the gas limit condition + // for regular transactions above. + trace!(target: "payload_builder", tx=?tx.hash(), ?block_blob_count, "skipping blob transaction because it would exceed the max blob count per block"); + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::Eip4844( + Eip4844PoolTransactionError::TooManyEip4844Blobs { + have: block_blob_count + tx_blob_count, + permitted: max_blob_count, + }, + ), + ); + continue + } + + let blob_sidecar_result = 'sidecar: { + let Some(sidecar) = + pool.get_blob(*tx.hash()).map_err(PayloadBuilderError::other)? + else { + break 'sidecar Err(Eip4844PoolTransactionError::MissingEip4844BlobSidecar) + }; + + if is_osaka { + if sidecar.is_eip7594() { + Ok(sidecar) + } else { + Err(Eip4844PoolTransactionError::UnexpectedEip4844SidecarAfterOsaka) + } + } else if sidecar.is_eip4844() { + Ok(sidecar) + } else { + Err(Eip4844PoolTransactionError::UnexpectedEip7594SidecarBeforeOsaka) + } + }; + + blob_tx_sidecar = match blob_sidecar_result { + Ok(sidecar) => Some(sidecar), + Err(error) => { + best_txs.mark_invalid(&pool_tx, InvalidPoolTransactionError::Eip4844(error)); + continue + } + }; + } + + // Execute the transaction + let gas_used = match builder.execute_transaction(tx.clone()) { + Ok(gas_used) => gas_used, + Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx { + error, .. + })) => { + if error.is_nonce_too_low() { + // if the nonce is too low, we can skip this transaction + trace!(target: "payload_builder", %error, ?tx, "skipping nonce too low transaction"); + } else { + // if the transaction is invalid, we can skip it and all of its + // descendants + trace!(target: "payload_builder", %error, ?tx, "skipping invalid transaction and its descendants"); + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::Consensus( + InvalidTransactionError::TxTypeNotSupported, + ), + ); + } + continue + } + // this is an error that we should treat as fatal for this attempt + Err(err) => return Err(PayloadBuilderError::evm(err)), + }; + + // add to the total blob gas used if the transaction successfully executed + if let Some(blob_tx) = tx.as_eip4844() { + block_blob_count += blob_tx.tx().blob_versioned_hashes.len() as u64; + + // if we've reached the max blob count, we can skip blob txs entirely + if block_blob_count == max_blob_count { + best_txs.skip_blobs(); + } + } + + block_transactions_rlp_length += tx.inner().length(); + + // update and add to total fees + let miner_fee = + tx.effective_tip_per_gas(base_fee).expect("fee is always valid; execution succeeded"); + total_fees += U256::from(miner_fee) * U256::from(gas_used); + cumulative_gas_used += gas_used; + + // Add blob tx sidecar to the payload. + if let Some(sidecar) = blob_tx_sidecar { + blob_sidecars.push_sidecar_variant(sidecar.as_ref().clone()); + } + } + + // check if we have a better block + if !is_better_payload(best_payload.as_ref(), total_fees) { + // Release db + drop(builder); + // can skip building the block + return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads }) + } + + let BlockBuilderOutcome { execution_result, block, .. } = builder.finish(&state_provider)?; + + let requests = chain_spec + .is_prague_active_at_timestamp(attributes.timestamp) + .then_some(execution_result.requests); + + let sealed_block = Arc::new(block.sealed_block().clone()); + debug!(target: "payload_builder", id=%attributes.id, sealed_block_header = ?sealed_block.sealed_header(), "sealed built block"); + + if is_osaka && sealed_block.rlp_length() > MAX_RLP_BLOCK_SIZE { + return Err(PayloadBuilderError::other(ConsensusError::BlockTooLarge { + rlp_length: sealed_block.rlp_length(), + max_rlp_length: MAX_RLP_BLOCK_SIZE, + })); + } + + let payload = BerachainBuiltPayload::new(attributes.id, sealed_block, total_fees, requests) + // add blob sidecars from the executed txs + .with_sidecars(blob_sidecars); + + Ok(BuildOutcome::Better { payload, cached_reads }) +} diff --git a/src/rpc/api.rs b/src/rpc/api.rs index 76eca4c5..f5521fe9 100644 --- a/src/rpc/api.rs +++ b/src/rpc/api.rs @@ -25,7 +25,7 @@ use reth_evm::{SpecFor, TxEnvFor}; use reth_rpc::eth::DevSigner; use reth_rpc_convert::SignableTxRequest; use reth_rpc_eth_api::{ - EthApiTypes, RpcNodeCore, RpcNodeCoreExt, + EthApiTypes, RpcNodeCore, RpcNodeCoreExt, RpcReceipt, helpers::{ AddDevSigners, Call, EthApiSpec, EthBlocks, EthCall, EthFees, EthState, EthTransactions, LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, LoadState, LoadTransaction, @@ -475,6 +475,30 @@ where Ok(hash) } + + /// Returns the transaction receipt for the given hash. + /// + /// Returns None if the transaction does not exist or is pending + /// Note: The tx receipt is not available for pending transactions. + /// TOOD: Override this to use Berachain Flashblocks + fn transaction_receipt( + &self, + hash: B256, + ) -> impl Future>, Self::Error>> + Send + where + Self: LoadReceipt + 'static, + { + async move { + match self.load_transaction_and_receipt(hash).await? { + Some((tx, meta, receipt)) => { + self.build_transaction_receipt(tx, meta, receipt).await.map(Some) + } + // TODO: In the none case, we should attempt to fetch from flashblock state + // The flashblock state needs to be ingested from WS stream + None => Ok(None), + } + } + } } impl LoadTransaction for BerachainApi From bbc019c45635851a354e9e936ddfb2c5b22573c4 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 09:15:03 +1100 Subject: [PATCH 13/25] progress --- Cargo.lock | 2 -- Cargo.toml | 3 ++- src/rblib_integration/platform.rs | 13 +++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a695b9a..aaaffc27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5628,7 +5628,6 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pipelines-macros" version = "0.3.1" -source = "git+https://github.com/flashbots/rblib#f4abbf12883e4486d6a3898d8b00613dec444618" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6105,7 +6104,6 @@ dependencies = [ [[package]] name = "rblib" version = "0.3.1" -source = "git+https://github.com/flashbots/rblib#f4abbf12883e4486d6a3898d8b00613dec444618" dependencies = [ "alloy", "alloy-evm", diff --git a/Cargo.toml b/Cargo.toml index 51aa9197..b738bbcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,8 @@ derive_more = "2.0.1" eyre = "0.6.12" sha2 = "0.10" -rblib = { git = "https://github.com/flashbots/rblib", version = "0.3.1", default-features = false } +# Requires minor modifications to rblib such that `FixedTransactions` is public +rblib = { path = "../rblib", features = ["optimism"] } # rpc jsonrpsee = "0.26.0" diff --git a/src/rblib_integration/platform.rs b/src/rblib_integration/platform.rs index e4b049fe..562854c6 100644 --- a/src/rblib_integration/platform.rs +++ b/src/rblib_integration/platform.rs @@ -13,6 +13,7 @@ use crate::{ }, pool::transaction::BerachainPooledTransaction, primitives::BerachainHeader, + rblib_integration::platform::pool::FixedTransactions, transaction::BerachainTxEnvelope, }; use alloy_consensus::Transaction; @@ -47,7 +48,8 @@ use reth_evm::{ use reth_payload_primitives::PayloadBuilderAttributes; use reth_primitives_traits::transaction::error::InvalidTransactionError; use reth_transaction_pool::{ - BestTransactionsAttributes, BestTransactionsFor, PoolTransaction, TransactionPool, + BestTransactions, BestTransactionsAttributes, BestTransactionsFor, PoolTransaction, + TransactionPool, ValidPoolTransaction, error::{Eip4844PoolTransactionError, InvalidPoolTransactionError}, noop::NoopTransactionPool, }; @@ -129,7 +131,14 @@ impl Platform for BerachainPlatform { NoopTransactionPool::new(), &builder_config, build_args, - || self.pool.best_transactions_with_attributes(attributes), + || { + transactions + as Box< + dyn BestTransactions< + Item = Arc>, + >, + > + }, )? .into_payload() .ok_or_else(|| PayloadBuilderError::MissingPayload) From 78e9bc9cb97ea6f62440f6d7afb5088a05d5e05f Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 09:24:59 +1100 Subject: [PATCH 14/25] clippy issues --- Cargo.toml | 2 +- src/rblib_integration/platform.rs | 19 ++++++++----------- src/rpc/api.rs | 18 ++++++++---------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b738bbcc..1907916c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ eyre = "0.6.12" sha2 = "0.10" # Requires minor modifications to rblib such that `FixedTransactions` is public -rblib = { path = "../rblib", features = ["optimism"] } +rblib = { path = "../rblib", default-features = false } # rpc jsonrpsee = "0.26.0" diff --git a/src/rblib_integration/platform.rs b/src/rblib_integration/platform.rs index 562854c6..aa148c14 100644 --- a/src/rblib_integration/platform.rs +++ b/src/rblib_integration/platform.rs @@ -3,7 +3,6 @@ use crate::{ chainspec::BerachainChainSpec, engine::{ BerachainEngineTypes, - builder::default_berachain_payload, payload::{BerachainBuiltPayload, BerachainPayloadBuilderAttributes}, }, hardforks::BerachainHardforks, @@ -17,7 +16,7 @@ use crate::{ transaction::BerachainTxEnvelope, }; use alloy_consensus::Transaction; -use alloy_eips::eip1559::{ETHEREUM_BLOCK_GAS_LIMIT, ETHEREUM_BLOCK_GAS_LIMIT_30M}; +use alloy_eips::eip1559::ETHEREUM_BLOCK_GAS_LIMIT_30M; use alloy_primitives::U256; use alloy_rlp::Encodable; use rblib::{ @@ -29,15 +28,14 @@ use rblib::{ reth::{ errors::{BlockExecutionError, BlockValidationError, ConsensusError}, ethereum::{ - chainspec::EthereumHardforks, - evm::revm::database::StateProviderDatabase, - provider::{StateProvider, StateProviderFactory}, + chainspec::EthereumHardforks, evm::revm::database::StateProviderDatabase, + provider::StateProvider, }, }, }; use reth::api::PayloadTypes; use reth_basic_payload_builder::{BuildArguments, BuildOutcome, PayloadConfig, is_better_payload}; -use reth_chainspec::{ChainSpecProvider, EthChainSpec}; +use reth_chainspec::EthChainSpec; use reth_consensus_common::validation::MAX_RLP_BLOCK_SIZE; use reth_ethereum_engine_primitives::BlobSidecars; use reth_ethereum_payload_builder::EthereumBuilderConfig; @@ -96,7 +94,7 @@ impl Platform for BerachainPlatform { gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_30M, // TODO: Get from config parent_beacon_block_root: attributes.parent_beacon_block_root, withdrawals: Some(attributes.withdrawals.clone()), - prev_proposer_pubkey: attributes.prev_proposer_pubkey.clone(), + prev_proposer_pubkey: attributes.prev_proposer_pubkey, } } @@ -131,7 +129,7 @@ impl Platform for BerachainPlatform { NoopTransactionPool::new(), &builder_config, build_args, - || { + |_| { transactions as Box< dyn BestTransactions< @@ -146,7 +144,7 @@ impl Platform for BerachainPlatform { } #[inline] -pub fn default_berachain_payload_for_platform( +pub fn default_berachain_payload_for_platform( evm_config: BerachainEvmConfig, chain_spec: &Arc>, state_provider: &dyn StateProvider, @@ -156,7 +154,6 @@ pub fn default_berachain_payload_for_platform( best_txs: F, ) -> Result, PayloadBuilderError> where - Client: StateProviderFactory + ChainSpecProvider, Pool: TransactionPool>, F: FnOnce(BestTransactionsAttributes) -> BestTransactionsFor, { @@ -370,7 +367,7 @@ where return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads }) } - let BlockBuilderOutcome { execution_result, block, .. } = builder.finish(&state_provider)?; + let BlockBuilderOutcome { execution_result, block, .. } = builder.finish(state_provider)?; let requests = chain_spec .is_prague_active_at_timestamp(attributes.timestamp) diff --git a/src/rpc/api.rs b/src/rpc/api.rs index f5521fe9..8893164b 100644 --- a/src/rpc/api.rs +++ b/src/rpc/api.rs @@ -481,22 +481,20 @@ where /// Returns None if the transaction does not exist or is pending /// Note: The tx receipt is not available for pending transactions. /// TOOD: Override this to use Berachain Flashblocks - fn transaction_receipt( + async fn transaction_receipt( &self, hash: B256, - ) -> impl Future>, Self::Error>> + Send + ) -> Result>, Self::Error> where Self: LoadReceipt + 'static, { - async move { - match self.load_transaction_and_receipt(hash).await? { - Some((tx, meta, receipt)) => { - self.build_transaction_receipt(tx, meta, receipt).await.map(Some) - } - // TODO: In the none case, we should attempt to fetch from flashblock state - // The flashblock state needs to be ingested from WS stream - None => Ok(None), + match self.load_transaction_and_receipt(hash).await? { + Some((tx, meta, receipt)) => { + self.build_transaction_receipt(tx, meta, receipt).await.map(Some) } + // TODO: In the none case, we should attempt to fetch from flashblock state + // The flashblock state needs to be ingested from WS stream + None => Ok(None), } } } From b185afa79a4dc7a188e0ef9c2fffcdfc4cd1069c Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 09:45:02 +1100 Subject: [PATCH 15/25] rblib --- Cargo.lock | 3 - Cargo.toml | 3 - src/bin/bera-sequencer.rs | 52 +++- src/lib.rs | 1 - src/sequencer/mod.rs | 10 - src/sequencer/node.rs | 83 ------ src/sequencer/payload_service.rs | 340 ----------------------- src/sequencer/payload_service_builder.rs | 66 ----- 8 files changed, 46 insertions(+), 512 deletions(-) delete mode 100644 src/sequencer/mod.rs delete mode 100644 src/sequencer/node.rs delete mode 100644 src/sequencer/payload_service.rs delete mode 100644 src/sequencer/payload_service_builder.rs diff --git a/Cargo.lock b/Cargo.lock index aaaffc27..0677eb60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1552,11 +1552,9 @@ dependencies = [ "reth-node-builder", "reth-node-core", "reth-node-ethereum", - "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", "reth-primitives-traits", - "reth-provider", "reth-rpc", "reth-rpc-convert", "reth-rpc-engine-api", @@ -1570,7 +1568,6 @@ dependencies = [ "test-fuzz", "thiserror 2.0.16", "tokio", - "tokio-util", "tracing", "vergen", "vergen-git2", diff --git a/Cargo.toml b/Cargo.toml index 1907916c..0fb0e3fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,11 +65,9 @@ reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-payload-validator = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } -reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-convert = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } reth-rpc-engine-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" } @@ -79,7 +77,6 @@ reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1 serde = { version = "1.0", features = ["derive"], default-features = false } thiserror = "2.0" tokio = "1.46.0" -tokio-util = "0.7" tracing = "0.1.41" [dev-dependencies] diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 85952b2d..6f8ff695 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -11,18 +11,36 @@ use bera_reth::{ chainspec::{BerachainChainSpec, BerachainChainSpecParser}, consensus::BerachainBeaconConsensus, evm::BerachainEvmFactory, - node::evm::config::BerachainEvmConfig, - sequencer::SequencerNode, + node::{BerachainNode, evm::config::BerachainEvmConfig}, + rblib_integration::BerachainPlatform, version::init_bera_version, }; use clap::Parser; +use rblib::{ + pool::{AppendOrders, OrderPool}, + prelude::{Loop, Pipeline}, + steps::OrderByPriorityFee, +}; use reth::CliRunner; use reth_cli_commands::node::NoArgs; use reth_ethereum_cli::Cli; -use reth_node_builder::NodeHandle; +use reth_node_builder::{Node, NodeHandle}; use std::sync::Arc; use tracing::info; +/// Basic block builder +/// +/// Block building strategy that builds blocks using the classic approach by +/// prepending sequencer transactions, then ordering the rest of the +/// transactions by tip. +fn build_sequencer_pipeline(pool: &OrderPool) -> Pipeline { + let pipeline = Pipeline::::named("classic") + .with_pipeline(Loop, (AppendOrders::from_pool(pool), OrderByPriorityFee::default())); + + pool.attach_pipeline(&pipeline); + pipeline +} + fn main() { // Install signal handler for better crash reporting reth_cli_util::sigsegv_handler::install(); @@ -43,13 +61,23 @@ fn main() { }; if let Err(err) = Cli::::parse() - .with_runner_and_components::( + .with_runner_and_components::( CliRunner::try_default_runtime().expect("Failed to create default runtime"), cli_components_builder, async move |builder, _| { info!(target: "reth::cli", "Launching Berachain Sequencer node"); - let NodeHandle { node: _node, node_exit_future } = - builder.node(SequencerNode).launch_with_debug_capabilities().await?; + let pool = OrderPool::::default(); + let pipeline = build_sequencer_pipeline(&pool); + let berachain_node = BerachainNode::default(); + + let NodeHandle { node: _node, node_exit_future } = builder + .with_types::() + .with_components( + berachain_node.components_builder().payload(pipeline.into_service()), + ) + .with_add_ons(berachain_node.add_ons()) + .launch_with_debug_capabilities() + .await?; node_exit_future.await }, @@ -59,3 +87,15 @@ fn main() { std::process::exit(1); } } + +/* + pub fn node( + self, + node: N, + ) -> NodeBuilderWithComponents, N::ComponentsBuilder, N::AddOns> + where + N: Node, ChainSpec = ChainSpec> + NodeTypesForProvider, + { + self.with_types().with_components(node.components_builder()).with_add_ons(node.add_ons()) + } +*/ diff --git a/src/lib.rs b/src/lib.rs index 0eeaa683..9bca0133 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,6 @@ pub mod pool; pub mod primitives; pub mod rblib_integration; pub mod rpc; -pub mod sequencer; #[cfg(test)] pub mod test_utils; pub mod transaction; diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs deleted file mode 100644 index 474465e3..00000000 --- a/src/sequencer/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Sequencer module for Berachain -//! -//! This module contains the custom payload builder for sequencing. - -pub mod node; -pub mod payload_service; -pub mod payload_service_builder; - -pub use node::SequencerNode; -pub use payload_service_builder::SequencerPayloadServiceBuilder; diff --git a/src/sequencer/node.rs b/src/sequencer/node.rs deleted file mode 100644 index fcadf7b6..00000000 --- a/src/sequencer/node.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::{ - chainspec::BerachainChainSpec, - consensus::BerachainConsensusBuilder, - engine::BerachainEngineTypes, - node::{BerachainAddOns, BerachainExecutorBuilder, BerachainPoolBuilder}, - primitives::{BerachainHeader, BerachainPrimitives}, - rpc::BerachainEthApiBuilder, - sequencer::SequencerPayloadServiceBuilder, - transaction::BerachainTxEnvelope, -}; -use reth::api::BlockTy; -use reth_engine_local::LocalPayloadAttributesBuilder; -use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; -use reth_node_builder::{ - DebugNode, Node, NodeAdapter, NodeComponentsBuilder, components::ComponentsBuilder, -}; -use reth_node_ethereum::node::EthereumNetworkBuilder; -use reth_payload_primitives::{PayloadAttributesBuilder, PayloadTypes}; -use reth_provider::EthStorage; -use std::sync::Arc; - -/// Custom sequencer node type for Berachain -#[derive(Debug, Clone, Default)] -pub struct SequencerNode; - -impl NodeTypes for SequencerNode { - type Primitives = BerachainPrimitives; - type ChainSpec = BerachainChainSpec; - type Storage = EthStorage; - type Payload = BerachainEngineTypes; -} - -impl Node for SequencerNode -where - N: FullNodeTypes, -{ - type ComponentsBuilder = ComponentsBuilder< - N, - BerachainPoolBuilder, - SequencerPayloadServiceBuilder, - EthereumNetworkBuilder, - BerachainExecutorBuilder, - BerachainConsensusBuilder, - >; - - type AddOns = BerachainAddOns< - NodeAdapter>::Components>, - BerachainEthApiBuilder, - crate::engine::validator::BerachainEngineValidatorBuilder, - >; - - fn components_builder(&self) -> Self::ComponentsBuilder { - ComponentsBuilder::default() - .node_types() - .pool(BerachainPoolBuilder) - .executor(BerachainExecutorBuilder) - .payload(SequencerPayloadServiceBuilder) - .network(EthereumNetworkBuilder::default()) - .consensus(BerachainConsensusBuilder) - } - - fn add_ons(&self) -> Self::AddOns { - BerachainAddOns::default() - } -} - -impl DebugNode for SequencerNode -where - N: FullNodeComponents, -{ - type RpcBlock = alloy_rpc_types::Block; - - fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> BlockTy { - rpc_block.into_consensus_block().convert_transactions() - } - - fn local_payload_attributes_builder( - chain_spec: &Self::ChainSpec, - ) -> impl PayloadAttributesBuilder<<::Payload as PayloadTypes>::PayloadAttributes> - { - LocalPayloadAttributesBuilder::new(Arc::new(chain_spec.clone())) - } -} diff --git a/src/sequencer/payload_service.rs b/src/sequencer/payload_service.rs deleted file mode 100644 index 54db6346..00000000 --- a/src/sequencer/payload_service.rs +++ /dev/null @@ -1,340 +0,0 @@ -//! Minimal payload service that properly handles subscriptions - -use crate::{ - chainspec::BerachainChainSpec, - engine::{ - BerachainEngineTypes, - builder::default_berachain_payload, - payload::{BerachainBuiltPayload, BerachainPayloadBuilderAttributes}, - }, - node::evm::BerachainEvmConfig, - primitives::BerachainHeader, - transaction::BerachainTxEnvelope, -}; -use alloy_primitives::B256; -use reth::{payload::PayloadId, providers::BlockReaderIdExt}; -use reth_basic_payload_builder::{BuildArguments, BuildOutcome, PayloadConfig}; -use reth_chainspec::ChainSpecProvider; -use reth_ethereum_payload_builder::EthereumBuilderConfig; -use reth_payload_builder::{PayloadBuilderError, PayloadBuilderHandle, PayloadServiceCommand}; -use reth_payload_primitives::PayloadBuilderAttributes; -use reth_provider::StateProviderFactory; -use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use std::{ - future::Future, - pin::Pin, - sync::Arc, - task::{Context, Poll}, -}; -use tokio::sync::{broadcast, mpsc, oneshot}; -use tokio_util::sync::CancellationToken; -use tracing::{error, info, warn}; - -/// State machine for the sequencer payload service. -/// -/// The sequencer follows a simple two-state pattern: -/// 1. `WaitingForForkchoiceUpdate`: Idle, waiting for a new payload build request -/// 2. `BuildingPayload`: Actively building a payload in a background task -/// -/// State transitions: -/// - `WaitingForForkchoiceUpdate` -> `BuildingPayload`: On `BuildNewPayload` command (fcu) -/// - `BuildingPayload` -> `WaitingForForkchoiceUpdate`: On `Resolve` command (getPayload) -/// -/// Only one payload can be built at a time to preserve pre-confirmations -pub enum SequencerStateMachine { - /// Waiting for a forkchoice update to trigger a new payload build. - /// This is the initial and idle state. - WaitingForForkchoiceUpdate, - /// Actively building a payload in a background blocking task. - /// The receiver is taken when the payload is resolved (getPayload). - BuildingPayload { - payload_id: PayloadId, - timestamp: u64, - /// Receiver for the built payload - becomes None after resolution - receiver: Option>>, - /// Token to signal the build task to stop adding transactions and finalize - cancel_token: CancellationToken, - }, -} - -pub struct SequencerPayloadService { - status: SequencerStateMachine, - command_rx: mpsc::UnboundedReceiver>, - events_tx: broadcast::Sender>, - client: Client, - pool: Pool, - evm_config: BerachainEvmConfig, - builder_config: EthereumBuilderConfig, -} - -impl SequencerPayloadService -where - Client: StateProviderFactory - + ChainSpecProvider - + Clone - + 'static - + BlockReaderIdExt

, - Pool: TransactionPool> + 'static, -{ - /// Creates a new minimal payload service with proper event handling - pub fn new( - client: Client, - pool: Pool, - evm_config: BerachainEvmConfig, - builder_config: EthereumBuilderConfig, - ) -> (Self, PayloadBuilderHandle) { - let (service_tx, command_rx) = mpsc::unbounded_channel(); - let (events_tx, _) = broadcast::channel(100); - - let service = Self { - command_rx, - events_tx, - status: SequencerStateMachine::WaitingForForkchoiceUpdate, - client, - pool, - evm_config, - builder_config, - }; - - let handle = PayloadBuilderHandle::new(service_tx); - (service, handle) - } - - /// Processes commands and manages state transitions. - /// - /// Command handling by state: - /// - `WaitingForForkchoiceUpdate`: - /// - `Subscribe`: Returns event receiver for payload notifications - /// - `BuildNewPayload`: Spawns build task, transitions to BuildingPayload - /// - `BuildingPayload`: - /// - `PayloadTimestamp`: Returns timestamp from stored attributes - /// - `Resolve`: Cancels build, waits for result, transitions to WaitingForForkchoiceUpdate - fn transition(&mut self, cmd: PayloadServiceCommand) { - match &mut self.status { - SequencerStateMachine::WaitingForForkchoiceUpdate => match cmd { - PayloadServiceCommand::Subscribe(tx) => { - info!(target: "sequencer", "Received Subscribe request - sending events receiver"); - let events_rx = self.events_tx.subscribe(); - let _ = tx.send(events_rx); - } - PayloadServiceCommand::BuildNewPayload(attr, tx) => { - info!(target: "sequencer", "Received BuildNewPayload request"); - let id = attr.payload_id(); - - info!(target: "sequencer", payload_id = ?id, "Starting async payload build"); - - // Create cancellation token and oneshot channel for the build - let cancel_token = CancellationToken::new(); - let (build_tx, build_rx) = oneshot::channel(); - - // Clone data for the blocking task - let client = self.client.clone(); - let pool = self.pool.clone(); - let evm_config = self.evm_config.clone(); - let builder_config = self.builder_config.clone(); - let cancel = cancel_token.clone(); - let attr_clone = attr.clone(); - - // Spawn a blocking task for CPU-intensive payload building - tokio::task::spawn_blocking(move || { - info!(target: "sequencer", payload_id = ?id, "Payload build blocking task started"); - - // Execute the CPU-intensive build synchronously - let result = Self::build_payload_blocking( - client, - pool, - evm_config, - builder_config, - attr_clone, - cancel, - ); - - match result { - Ok(payload) => { - info!(target: "sequencer", payload_id = ?id, "Payload build completed successfully"); - let _ = build_tx.send(Ok(payload)); - } - Err(err) => { - error!(target: "sequencer", payload_id = ?id, ?err, "Payload build failed"); - let _ = build_tx.send(Err(err)); - } - } - }); - - self.status = SequencerStateMachine::BuildingPayload { - payload_id: id, - timestamp: attr.timestamp, - receiver: Some(build_rx), - cancel_token, - }; - - // Immediately respond with the payload ID - let _ = tx.send(Ok(id)); - } - cmd => { - warn!(target: "sequencer", ?cmd, "Received unexpected PayloadServiceCommand while waiting for forkchoice update"); - } - }, - SequencerStateMachine::BuildingPayload { - payload_id, - timestamp, - receiver, - cancel_token, - } => match cmd { - PayloadServiceCommand::PayloadTimestamp(id, tx) => { - let timestamp = if id == *payload_id { Some(Ok(*timestamp)) } else { None }; - let _ = tx.send(timestamp); - } - PayloadServiceCommand::Resolve(id, _kind, tx) => { - info!(target: "sequencer", payload_id = ?id, "Received Resolve request for payload"); - - if id != *payload_id { - warn!(target: "sequencer", payload_id = ?id, current_id = ?payload_id, "Resolve request for different payload ID"); - let _ = tx.send(None); - return; - } - - if let Some(receiver) = receiver.take() { - info!(target: "sequencer", payload_id = ?payload_id, "Signaling build task to complete"); - cancel_token.cancel(); - - info!(target: "sequencer", payload_id = ?payload_id, "Waiting for build task to complete"); - - let result = tokio::task::block_in_place(|| { - tokio::runtime::Handle::current().block_on(receiver) - }); - - let response = match result { - Ok(Ok(payload)) => { - info!(target: "sequencer", payload_id = ?payload_id, "Payload successfully retrieved"); - Some(Box::pin(async move { Ok(payload) }) as _) - } - Ok(Err(err)) => { - error!(target: "sequencer", payload_id = ?payload_id, ?err, "Payload build failed"); - Some(Box::pin(async move { Err(err) }) as _) - } - Err(_) => { - warn!(target: "sequencer", payload_id = ?payload_id, "Build task dropped without result"); - None - } - }; - - let _ = tx.send(response); - - self.status = SequencerStateMachine::WaitingForForkchoiceUpdate; - info!(target: "sequencer", "Transitioned to WaitingForForkchoiceUpdate state"); - } else { - warn!(target: "sequencer", payload_id = ?payload_id, "Payload already resolved"); - let _ = tx.send(None); - } - } - cmd => { - warn!(target: "sequencer", ?cmd, "Received unexpected PayloadServiceCommand while BuildingPayload"); - } - }, - } - } - - fn build_payload_blocking( - client: Client, - pool: Pool, - evm_config: BerachainEvmConfig, - builder_config: EthereumBuilderConfig, - attributes: BerachainPayloadBuilderAttributes, - _cancel_token: CancellationToken, - ) -> Result { - let payload_id = attributes.id; - info!(target: "sequencer", payload_id = ?payload_id, parent = ?attributes.parent, timestamp = attributes.timestamp, "Beginning payload construction"); - - let parent_header = if attributes.parent().is_zero() { - // Use latest header for genesis block case - client - .latest_header() - .map_err(PayloadBuilderError::from)? - .ok_or_else(|| PayloadBuilderError::MissingParentHeader(B256::ZERO))? - } else { - // Fetch specific header by hash - client - .sealed_header_by_hash(attributes.parent()) - .map_err(PayloadBuilderError::from)? - .ok_or_else(|| PayloadBuilderError::MissingParentHeader(attributes.parent()))? - }; - - info!(target: "sequencer", payload_id = ?payload_id, parent_number = parent_header.number, "Retrieved parent block"); - - // Create the payload config - let config = PayloadConfig::new(Arc::new(parent_header.clone()), attributes.clone()); - - // TODO: The cancel token should be passed to default_berachain_payload and checked - // after each transaction is processed. When cancelled, it should stop processing - // more transactions and immediately finalize the block with transactions processed so far. - // This will enable getPayload to signal "stop adding txs and return what you have". - // For now, we don't pass the cancel token to avoid complexity. - let args = BuildArguments::new( - Default::default(), // cached_reads - config, - Default::default(), // cancel token - TODO: integrate with our cancel_token - None, // best_payload - ); - - info!(target: "sequencer", payload_id = ?payload_id, "Calling default_berachain_payload to build block"); - - // Build the payload using the standard function - let outcome = default_berachain_payload( - evm_config, - client.clone(), - pool.clone(), - builder_config, - args, - |attrs| pool.best_transactions_with_attributes(attrs), - )?; - - // Return the built payload - match outcome { - BuildOutcome::Better { payload, .. } => { - let block_number = payload.block.header().number; - let tx_count = payload.block.body().transactions.len(); - info!(target: "sequencer", - payload_id = ?payload_id, - block_number = block_number, - tx_count = tx_count, - "Successfully built payload" - ); - Ok(payload) - } - _ => { - warn!(target: "sequencer", payload_id = ?payload_id, "Build did not produce a better payload"); - panic!("cannot happen as payloads will always be better"); - } - } - } -} - -impl Future for SequencerPayloadService -where - Client: StateProviderFactory - + ChainSpecProvider - + Clone - + 'static - + BlockReaderIdExt
- + Unpin, - Pool: TransactionPool> - + Unpin - + 'static, -{ - type Output = (); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.get_mut(); - loop { - match this.command_rx.poll_recv(cx) { - Poll::Ready(Some(cmd)) => this.transition(cmd), - Poll::Ready(None) => { - info!(target: "sequencer", "Payload service channel closed, shutting down"); - return Poll::Ready(()); - } - Poll::Pending => return Poll::Pending, - } - } - } -} diff --git a/src/sequencer/payload_service_builder.rs b/src/sequencer/payload_service_builder.rs deleted file mode 100644 index 5ec52668..00000000 --- a/src/sequencer/payload_service_builder.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Custom payload service builder for the sequencer - -use crate::{ - engine::BerachainEngineTypes, node::evm::BerachainEvmConfig, - sequencer::payload_service::SequencerPayloadService, -}; -use reth::chainspec::EthChainSpec; -use reth_node_api::FullNodeTypes; -use reth_node_builder::{BuilderContext, PayloadBuilderConfig, components::PayloadServiceBuilder}; -use reth_payload_builder::PayloadBuilderHandle; -use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use tracing::info; - -/// Custom payload service builder that spawns a NoopPayloadBuilder for now -#[derive(Debug, Clone, Default)] -pub struct SequencerPayloadServiceBuilder; - -impl PayloadServiceBuilder for SequencerPayloadServiceBuilder -where - N: FullNodeTypes< - Types: reth_node_api::NodeTypes< - Payload = BerachainEngineTypes, - ChainSpec = crate::chainspec::BerachainChainSpec, - Primitives = crate::primitives::BerachainPrimitives, - >, - >, - N::Provider: reth_provider::StateProviderFactory - + reth_chainspec::ChainSpecProvider - + reth_provider::BlockReader - + Clone - + Unpin - + 'static, - Pool: TransactionPool< - Transaction: PoolTransaction, - > + Unpin - + Clone - + 'static, -{ - async fn spawn_payload_builder_service( - self, - ctx: &BuilderContext, - pool: Pool, - evm_config: BerachainEvmConfig, - ) -> eyre::Result::Payload>> { - info!(target: "sequencer", "Spawning minimal sequencer payload service"); - - // Get configuration - let conf = ctx.payload_builder_config(); - let chain = ctx.chain_spec().chain(); - let gas_limit = conf.gas_limit_for(chain); - - let builder_config = - reth_ethereum_payload_builder::EthereumBuilderConfig::new().with_gas_limit(gas_limit); - - let (service, handle) = - SequencerPayloadService::new(ctx.provider().clone(), pool, evm_config, builder_config); - - // Spawn the service to run indefinitely - tokio::spawn(async move { - service.await; - info!(target: "sequencer", "Payload service terminated"); - }); - - Ok(handle) - } -} From 0a0ac5adad55c1d95626000c46562251e5ca5574 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 09:50:24 +1100 Subject: [PATCH 16/25] cleanup --- src/bin/bera-sequencer.rs | 2 +- src/lib.rs | 2 +- .../platform.rs => platform/mod.rs} | 20 +++++++++++++++++-- src/rblib_integration/limits.rs | 19 ------------------ src/rblib_integration/mod.rs | 5 ----- 5 files changed, 20 insertions(+), 28 deletions(-) rename src/{rblib_integration/platform.rs => platform/mod.rs} (96%) delete mode 100644 src/rblib_integration/limits.rs delete mode 100644 src/rblib_integration/mod.rs diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 6f8ff695..06afdfa1 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -12,7 +12,7 @@ use bera_reth::{ consensus::BerachainBeaconConsensus, evm::BerachainEvmFactory, node::{BerachainNode, evm::config::BerachainEvmConfig}, - rblib_integration::BerachainPlatform, + platform::BerachainPlatform, version::init_bera_version, }; use clap::Parser; diff --git a/src/lib.rs b/src/lib.rs index 9bca0133..e7f2bf71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,9 +9,9 @@ pub mod evm; pub mod genesis; pub mod hardforks; pub mod node; +pub mod platform; pub mod pool; pub mod primitives; -pub mod rblib_integration; pub mod rpc; #[cfg(test)] pub mod test_utils; diff --git a/src/rblib_integration/platform.rs b/src/platform/mod.rs similarity index 96% rename from src/rblib_integration/platform.rs rename to src/platform/mod.rs index aa148c14..9d3ae5c7 100644 --- a/src/rblib_integration/platform.rs +++ b/src/platform/mod.rs @@ -1,4 +1,3 @@ -use super::limits::BerachainLimits; use crate::{ chainspec::BerachainChainSpec, engine::{ @@ -12,7 +11,6 @@ use crate::{ }, pool::transaction::BerachainPooledTransaction, primitives::BerachainHeader, - rblib_integration::platform::pool::FixedTransactions, transaction::BerachainTxEnvelope, }; use alloy_consensus::Transaction; @@ -54,6 +52,24 @@ use reth_transaction_pool::{ use std::sync::Arc; use tracing::{debug, trace, warn}; +use rblib::prelude::pool::FixedTransactions; +use std::time::Duration; + +/// Default limits for Berachain payload building +#[derive(Debug, Clone, Default)] +pub struct BerachainLimits; + +impl PlatformLimits for BerachainLimits { + fn create(&self, _block: &BlockContext) -> Limits { + Limits { + gas_limit: 30_000_000, // TODO: calculate correctly + blob_params: None, // TODO: Get blob configuration from chainspec + max_transactions: Some(1_000), + deadline: Some(Duration::from_secs(2)), // bera block time + } + } +} + /// Platform implementation for Berachain /// /// This type implements rblib's Platform trait for Berachain, diff --git a/src/rblib_integration/limits.rs b/src/rblib_integration/limits.rs deleted file mode 100644 index 4fc09b59..00000000 --- a/src/rblib_integration/limits.rs +++ /dev/null @@ -1,19 +0,0 @@ -use rblib::prelude::*; -use std::time::Duration; - -use super::platform::BerachainPlatform; - -/// Default limits for Berachain payload building -#[derive(Debug, Clone, Default)] -pub struct BerachainLimits; - -impl PlatformLimits for BerachainLimits { - fn create(&self, _block: &BlockContext) -> Limits { - Limits { - gas_limit: 30_000_000, // TODO: calculate correctly - blob_params: None, // TODO: Get blob configuration from chainspec - max_transactions: Some(1_000), - deadline: Some(Duration::from_secs(2)), // bera block time - } - } -} diff --git a/src/rblib_integration/mod.rs b/src/rblib_integration/mod.rs deleted file mode 100644 index cc9244ce..00000000 --- a/src/rblib_integration/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod limits; -pub mod platform; - -pub use limits::BerachainLimits; -pub use platform::BerachainPlatform; From a184d7e75bb97b65158de495487d4230ec532f9c Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:05:28 +1100 Subject: [PATCH 17/25] error in trait bounds --- src/bin/bera-sequencer.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 06afdfa1..09cd4969 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -17,7 +17,7 @@ use bera_reth::{ }; use clap::Parser; use rblib::{ - pool::{AppendOrders, OrderPool}, + pool::{AppendOrders, HostNodeInstaller, OrderPool}, prelude::{Loop, Pipeline}, steps::OrderByPriorityFee, }; @@ -73,7 +73,10 @@ fn main() { let NodeHandle { node: _node, node_exit_future } = builder .with_types::() .with_components( - berachain_node.components_builder().payload(pipeline.into_service()), + berachain_node + .components_builder() + .attach_pool(&pool) + .payload(pipeline.into_service()), ) .with_add_ons(berachain_node.add_ons()) .launch_with_debug_capabilities() @@ -87,15 +90,3 @@ fn main() { std::process::exit(1); } } - -/* - pub fn node( - self, - node: N, - ) -> NodeBuilderWithComponents, N::ComponentsBuilder, N::AddOns> - where - N: Node, ChainSpec = ChainSpec> + NodeTypesForProvider, - { - self.with_types().with_components(node.components_builder()).with_add_ons(node.add_ons()) - } -*/ From 112063c5821cec87194541017b06d56b86c95e76 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:38:29 +1100 Subject: [PATCH 18/25] gmm --- src/bin/bera-sequencer.rs | 5 +++-- src/pool/mod.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 09cd4969..61222777 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -21,7 +21,7 @@ use rblib::{ prelude::{Loop, Pipeline}, steps::OrderByPriorityFee, }; -use reth::CliRunner; +use reth::{CliRunner, revm::interpreter::instructions::arithmetic::add}; use reth_cli_commands::node::NoArgs; use reth_ethereum_cli::Cli; use reth_node_builder::{Node, NodeHandle}; @@ -69,6 +69,7 @@ fn main() { let pool = OrderPool::::default(); let pipeline = build_sequencer_pipeline(&pool); let berachain_node = BerachainNode::default(); + let add_ons = berachain_node.add_ons(); let NodeHandle { node: _node, node_exit_future } = builder .with_types::() @@ -78,7 +79,7 @@ fn main() { .attach_pool(&pool) .payload(pipeline.into_service()), ) - .with_add_ons(berachain_node.add_ons()) + .with_add_ons(add_ons) .launch_with_debug_capabilities() .await?; diff --git a/src/pool/mod.rs b/src/pool/mod.rs index 58f61be1..801cb1f5 100644 --- a/src/pool/mod.rs +++ b/src/pool/mod.rs @@ -19,7 +19,7 @@ use reth_transaction_pool::TransactionValidationTaskExecutor; use std::{fmt::Debug, time::SystemTime}; use tracing::{debug, info}; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone, Copy)] pub struct BerachainPoolBuilder; impl PoolBuilder for BerachainPoolBuilder From 8c532a93e4a70000ee59a656dcc191bd26e10595 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:43:53 +1100 Subject: [PATCH 19/25] works --- src/bin/bera-sequencer.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 61222777..9bd81ebb 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -10,9 +10,11 @@ static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::ne use bera_reth::{ chainspec::{BerachainChainSpec, BerachainChainSpecParser}, consensus::BerachainBeaconConsensus, + engine::{rpc::BerachainEngineApiBuilder, validator::BerachainEngineValidatorBuilder}, evm::BerachainEvmFactory, node::{BerachainNode, evm::config::BerachainEvmConfig}, platform::BerachainPlatform, + rpc::{BerachainAddOns, BerachainEthApiBuilder}, version::init_bera_version, }; use clap::Parser; @@ -21,7 +23,7 @@ use rblib::{ prelude::{Loop, Pipeline}, steps::OrderByPriorityFee, }; -use reth::{CliRunner, revm::interpreter::instructions::arithmetic::add}; +use reth::CliRunner; use reth_cli_commands::node::NoArgs; use reth_ethereum_cli::Cli; use reth_node_builder::{Node, NodeHandle}; @@ -69,7 +71,15 @@ fn main() { let pool = OrderPool::::default(); let pipeline = build_sequencer_pipeline(&pool); let berachain_node = BerachainNode::default(); - let add_ons = berachain_node.add_ons(); + + // Construct add-ons with explicit type parameters to allow inference of the complex + // pool type + let add_ons: BerachainAddOns< + _, + BerachainEthApiBuilder, + BerachainEngineValidatorBuilder, + BerachainEngineApiBuilder, + > = BerachainAddOns::default(); let NodeHandle { node: _node, node_exit_future } = builder .with_types::() @@ -80,7 +90,7 @@ fn main() { .payload(pipeline.into_service()), ) .with_add_ons(add_ons) - .launch_with_debug_capabilities() + .launch() .await?; node_exit_future.await From f0b897c4b4eea66c7605d6ee1a588aec92c4e3f2 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:44:54 +1100 Subject: [PATCH 20/25] works --- src/bin/bera-sequencer.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 9bd81ebb..71ccfc96 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -72,8 +72,7 @@ fn main() { let pipeline = build_sequencer_pipeline(&pool); let berachain_node = BerachainNode::default(); - // Construct add-ons with explicit type parameters to allow inference of the complex - // pool type + // Helps compiler let add_ons: BerachainAddOns< _, BerachainEthApiBuilder, @@ -90,7 +89,7 @@ fn main() { .payload(pipeline.into_service()), ) .with_add_ons(add_ons) - .launch() + .launch_with_debug_capabilities() .await?; node_exit_future.await From 097500cc7f35a6a47df1ec3fcb92e9b5a4fb61ee Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:49:05 +1100 Subject: [PATCH 21/25] Update bera-sequencer.rs --- src/bin/bera-sequencer.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 71ccfc96..8cdb3f95 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -21,7 +21,7 @@ use clap::Parser; use rblib::{ pool::{AppendOrders, HostNodeInstaller, OrderPool}, prelude::{Loop, Pipeline}, - steps::OrderByPriorityFee, + steps::{OrderByPriorityFee, RemoveRevertedTransactions}, }; use reth::CliRunner; use reth_cli_commands::node::NoArgs; @@ -30,14 +30,16 @@ use reth_node_builder::{Node, NodeHandle}; use std::sync::Arc; use tracing::info; -/// Basic block builder -/// -/// Block building strategy that builds blocks using the classic approach by -/// prepending sequencer transactions, then ordering the rest of the -/// transactions by tip. +/// Example Berachain Sequencer with Revert Protection fn build_sequencer_pipeline(pool: &OrderPool) -> Pipeline { - let pipeline = Pipeline::::named("classic") - .with_pipeline(Loop, (AppendOrders::from_pool(pool), OrderByPriorityFee::default())); + let pipeline = Pipeline::::named("classic").with_pipeline( + Loop, + ( + AppendOrders::from_pool(pool), + OrderByPriorityFee::default(), + RemoveRevertedTransactions::default(), + ), + ); pool.attach_pipeline(&pipeline); pipeline From 3155ad093afa02caebd93303089f628620ff983b Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:49:54 +1100 Subject: [PATCH 22/25] Update bera-sequencer.rs --- src/bin/bera-sequencer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index 8cdb3f95..b98e97d9 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -30,8 +30,8 @@ use reth_node_builder::{Node, NodeHandle}; use std::sync::Arc; use tracing::info; -/// Example Berachain Sequencer with Revert Protection -fn build_sequencer_pipeline(pool: &OrderPool) -> Pipeline { +/// Example Berachain builder pipeline with Revert Protection +fn berachain_builder_pipeline(pool: &OrderPool) -> Pipeline { let pipeline = Pipeline::::named("classic").with_pipeline( Loop, ( From a995c8ee15f63feddd6e7d326291787f4450f1e8 Mon Sep 17 00:00:00 2001 From: Rez Date: Mon, 24 Nov 2025 10:51:46 +1100 Subject: [PATCH 23/25] Update mod.rs --- src/platform/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 9d3ae5c7..6a2ff996 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -196,8 +196,6 @@ where ) .map_err(PayloadBuilderError::other)?; - // let chain_spec = client.chain_spec(); - debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); let mut cumulative_gas_used = 0; let block_gas_limit: u64 = builder.evm_mut().block().gas_limit; From bf2e818c0bc7194dff4a7d4e1ce805c89729655e Mon Sep 17 00:00:00 2001 From: Rez Date: Thu, 27 Nov 2025 03:55:34 +1100 Subject: [PATCH 24/25] Update mod.rs --- src/platform/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 6a2ff996..9c8b1fe3 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -52,6 +52,7 @@ use reth_transaction_pool::{ use std::sync::Arc; use tracing::{debug, trace, warn}; +use crate::evm::BerachainEvmFactory; use rblib::prelude::pool::FixedTransactions; use std::time::Duration; @@ -88,8 +89,6 @@ impl Platform for BerachainPlatform { where P: traits::PlatformExecBounds, { - // Create EVM config with the Berachain chain spec - use crate::evm::BerachainEvmFactory; BerachainEvmConfig::new_with_evm_factory(chainspec, BerachainEvmFactory::default()) } From f6b8441372d7d640dbe605c10f6a115f152b37c3 Mon Sep 17 00:00:00 2001 From: Rez Date: Thu, 27 Nov 2025 03:56:20 +1100 Subject: [PATCH 25/25] Update bera-sequencer.rs --- src/bin/bera-sequencer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/bera-sequencer.rs b/src/bin/bera-sequencer.rs index b98e97d9..25e69de8 100644 --- a/src/bin/bera-sequencer.rs +++ b/src/bin/bera-sequencer.rs @@ -71,7 +71,7 @@ fn main() { async move |builder, _| { info!(target: "reth::cli", "Launching Berachain Sequencer node"); let pool = OrderPool::::default(); - let pipeline = build_sequencer_pipeline(&pool); + let pipeline = berachain_builder_pipeline(&pool); let berachain_node = BerachainNode::default(); // Helps compiler