1#![allow(missing_docs)]
3
4#[global_allocator]
5static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator();
6
7mod evm;
8mod evm_config;
9
10use alloy_rpc_types::engine::ExecutionData;
11use clap::Parser;
12use evm_config::{BbEvmConfig, BigBlockData};
13use reth_chainspec::{ChainSpec, EthereumHardforks};
14use reth_consensus::noop::NoopConsensus;
15use reth_ethereum_cli::{chainspec::EthereumChainSpecParser, interface::Cli};
16use reth_ethereum_primitives::{Block, EthPrimitives};
17use reth_evm_ethereum::EthEvmConfig;
18use reth_node_api::{
19 AddOnsContext, FullNodeComponents, NewPayloadError, NodeTypes, PayloadTypes, PayloadValidator,
20};
21use reth_node_builder::{
22 components::{
23 BasicPayloadServiceBuilder, ComponentsBuilder, ConsensusBuilder, ExecutorBuilder,
24 },
25 node::FullNodeTypes,
26 rpc::{NoopEngineApiBuilder, PayloadValidatorBuilder, RpcAddOns},
27 BuilderContext, Node, NodeAdapter,
28};
29use reth_node_core::args::DefaultEngineValues;
30use reth_node_ethereum::{
31 EthPayloadTypes, EthereumEngineValidator, EthereumEthApiBuilder, EthereumNetworkBuilder,
32 EthereumNode, EthereumPayloadBuilder, EthereumPoolBuilder,
33};
34use reth_primitives_traits::SealedBlock;
35use reth_provider::EthStorage;
36use revm_primitives::Bytes;
37use tracing::info;
38
39#[derive(Debug, Clone, Default)]
40pub struct BbPayloadTypes;
41
42impl PayloadTypes for BbPayloadTypes {
43 type ExecutionData = BigBlockData<ExecutionData>;
44 type BuiltPayload = <EthPayloadTypes as PayloadTypes>::BuiltPayload;
45 type PayloadAttributes = <EthPayloadTypes as PayloadTypes>::PayloadAttributes;
46
47 fn block_to_payload(
48 _block: SealedBlock<
49 <<Self::BuiltPayload as reth_node_api::BuiltPayload>::Primitives as reth_node_api::NodePrimitives>::Block,
50 >,
51 _bal: Option<Bytes>,
52 ) -> Self::ExecutionData {
53 unreachable!()
54 }
55}
56
57#[derive(Debug, Default, Clone)]
58pub struct BbEngineValidatorBuilder;
59
60impl<Node> PayloadValidatorBuilder<Node> for BbEngineValidatorBuilder
61where
62 Node: FullNodeComponents<Types = BbNode>,
63{
64 type Validator = BbEngineValidator;
65
66 async fn build(self, ctx: &AddOnsContext<'_, Node>) -> eyre::Result<Self::Validator> {
67 Ok(BbEngineValidator { inner: EthereumEngineValidator::new(ctx.config.chain.clone()) })
68 }
69}
70
71#[derive(Debug, Clone)]
72pub struct BbEngineValidator {
73 inner: EthereumEngineValidator,
74}
75
76impl PayloadValidator<BbPayloadTypes> for BbEngineValidator {
77 type Block = Block;
78
79 fn convert_payload_to_block(
80 &self,
81 payload: BigBlockData<ExecutionData>,
82 ) -> Result<SealedBlock<Block>, NewPayloadError> {
83 let mut blocks = payload
84 .env_switches
85 .into_iter()
86 .map(|data| {
87 PayloadValidator::<EthPayloadTypes>::convert_payload_to_block(&self.inner, data)
88 })
89 .collect::<Result<Vec<SealedBlock<Block>>, NewPayloadError>>()?;
90
91 let (mut block, hash) = blocks.pop().unwrap().split();
92
93 block.header.number = payload.block_number;
95
96 if let Some(first) = blocks.first() {
99 block.header.parent_hash = first.parent_hash;
100 }
101
102 block.header.gas_used += blocks.iter().map(|b| b.gas_used).sum::<u64>();
104
105 block.body.transactions = blocks
108 .into_iter()
109 .flat_map(|b| b.into_body().transactions)
110 .chain(core::mem::take(&mut block.body.transactions))
111 .collect();
112
113 Ok(SealedBlock::new_unchecked(block, hash))
115 }
116}
117
118#[derive(Debug, Default)]
124#[non_exhaustive]
125pub struct BbExecutorBuilder;
126
127impl<Node> ExecutorBuilder<Node> for BbExecutorBuilder
128where
129 Node: FullNodeTypes<
130 Types: NodeTypes<
131 ChainSpec: reth_ethereum_forks::Hardforks
132 + alloy_evm::eth::spec::EthExecutorSpec
133 + EthereumHardforks,
134 Primitives = EthPrimitives,
135 >,
136 >,
137{
138 type EVM = BbEvmConfig<<Node::Types as NodeTypes>::ChainSpec>;
139
140 async fn build_evm(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
141 Ok(BbEvmConfig::new(EthEvmConfig::new(ctx.chain_spec())))
142 }
143}
144
145#[derive(Debug, Clone, Default)]
151#[non_exhaustive]
152pub struct BbNode;
153
154impl NodeTypes for BbNode {
155 type Primitives = EthPrimitives;
156 type ChainSpec = ChainSpec;
157 type Storage = EthStorage;
158 type Payload = BbPayloadTypes;
159}
160
161impl<N> Node<N> for BbNode
162where
163 N: FullNodeTypes<Types = Self>,
164{
165 type ComponentsBuilder = ComponentsBuilder<
166 N,
167 EthereumPoolBuilder,
168 BasicPayloadServiceBuilder<EthereumPayloadBuilder>,
169 EthereumNetworkBuilder,
170 BbExecutorBuilder,
171 BbConsensusBuilder,
172 >;
173
174 type AddOns = RpcAddOns<
175 NodeAdapter<N>,
176 EthereumEthApiBuilder,
177 BbEngineValidatorBuilder,
178 NoopEngineApiBuilder,
179 >;
180
181 fn components_builder(&self) -> Self::ComponentsBuilder {
182 EthereumNode::components()
183 .executor(BbExecutorBuilder::default())
184 .consensus(BbConsensusBuilder)
185 }
186
187 fn add_ons(&self) -> Self::AddOns {
188 Default::default()
189 }
190}
191
192#[derive(Debug, Default, Clone, Copy)]
198pub struct BbConsensusBuilder;
199
200impl<Node> ConsensusBuilder<Node> for BbConsensusBuilder
201where
202 Node: FullNodeTypes<Types: NodeTypes<Primitives = EthPrimitives>>,
203{
204 type Consensus = NoopConsensus;
205
206 async fn build_consensus(self, _ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
207 Ok(NoopConsensus::default())
208 }
209}
210
211fn main() {
216 reth_cli_util::sigsegv_handler::install();
217
218 if std::env::var_os("RUST_BACKTRACE").is_none() {
219 unsafe { std::env::set_var("RUST_BACKTRACE", "1") };
220 }
221
222 let _ = DefaultEngineValues::default().with_bal_parallel_execution_disabled(false).try_init();
223
224 if let Err(err) = Cli::<EthereumChainSpecParser>::parse().run(async move |builder, _| {
225 info!(target: "reth::cli", "Launching big block node");
226 let handle = builder.launch_node(BbNode::default()).await?;
227
228 handle.wait_for_node_exit().await
229 }) {
230 eprintln!("Error: {err:?}");
231 std::process::exit(1);
232 }
233}