From a67b53962484e916b645d3ad19902fadb71f004e Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 7 Apr 2025 13:46:47 +0200 Subject: [PATCH 01/11] Initial commit From f4412e1c43976d7a992bf3456876f379f79b614b Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 7 Apr 2025 15:00:33 +0200 Subject: [PATCH 02/11] Initial project structure --- .gitignore | 1 + sz-poc-offsite-2025/Cargo.toml | 13 +++++++++++++ sz-poc-offsite-2025/node/Cargo.toml | 6 ++++++ sz-poc-offsite-2025/node/src/main.rs | 2 ++ 4 files changed, 22 insertions(+) create mode 100644 sz-poc-offsite-2025/Cargo.toml create mode 100644 sz-poc-offsite-2025/node/Cargo.toml create mode 100644 sz-poc-offsite-2025/node/src/main.rs diff --git a/.gitignore b/.gitignore index 1e7caa9..8b98abd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Cargo.lock target/ +.vscode \ No newline at end of file diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml new file mode 100644 index 0000000..fcc98c6 --- /dev/null +++ b/sz-poc-offsite-2025/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +members = ["node"] +resolver = "3" + +[workspace.package] +edition = "2024" + +[workspace.dependencies] +# Internal +node = { path = "node" } + +# External +tokio = { version = "1.0" } diff --git a/sz-poc-offsite-2025/node/Cargo.toml b/sz-poc-offsite-2025/node/Cargo.toml new file mode 100644 index 0000000..cfdc2e1 --- /dev/null +++ b/sz-poc-offsite-2025/node/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "node" +edition = { workspace = true } + +[dependencies] +tokio = { workspace = true, features = ["full"] } diff --git a/sz-poc-offsite-2025/node/src/main.rs b/sz-poc-offsite-2025/node/src/main.rs new file mode 100644 index 0000000..7f755fb --- /dev/null +++ b/sz-poc-offsite-2025/node/src/main.rs @@ -0,0 +1,2 @@ +#[tokio::main] +async fn main() {} From 8ee6c1c12d24441464ab3126c71df7ed6ad9d7d0 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 9 Apr 2025 09:07:39 +0200 Subject: [PATCH 03/11] Custom binary wrapping reth works --- sz-poc-offsite-2025/Cargo.toml | 11 +++++-- sz-poc-offsite-2025/evm/evm-node/Cargo.toml | 11 +++++++ sz-poc-offsite-2025/evm/evm-node/src/main.rs | 34 ++++++++++++++++++++ sz-poc-offsite-2025/node/Cargo.toml | 6 ---- sz-poc-offsite-2025/node/src/main.rs | 2 -- 5 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 sz-poc-offsite-2025/evm/evm-node/Cargo.toml create mode 100644 sz-poc-offsite-2025/evm/evm-node/src/main.rs delete mode 100644 sz-poc-offsite-2025/node/Cargo.toml delete mode 100644 sz-poc-offsite-2025/node/src/main.rs diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml index fcc98c6..e4f16ed 100644 --- a/sz-poc-offsite-2025/Cargo.toml +++ b/sz-poc-offsite-2025/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["node"] +members = ["evm/evm-node"] resolver = "3" [workspace.package] @@ -7,7 +7,12 @@ edition = "2024" [workspace.dependencies] # Internal -node = { path = "node" } +evm-node = { path = "evm/evm-node" } # External -tokio = { version = "1.0" } +clap = { version = "4.5" } +futures-util = { version = "0.3" } +jsonrpsee = { version = "0.24" } +reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } +reth-cli-commands = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } +reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } diff --git a/sz-poc-offsite-2025/evm/evm-node/Cargo.toml b/sz-poc-offsite-2025/evm/evm-node/Cargo.toml new file mode 100644 index 0000000..b67508d --- /dev/null +++ b/sz-poc-offsite-2025/evm/evm-node/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "evm-node" +edition = { workspace = true } + +[dependencies] +clap = { workspace = true } +futures-util = { workspace = true } +jsonrpsee = { workspace = true } +reth = { workspace = true } +reth-cli-commands = { workspace = true } +reth-node-ethereum = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/evm-node/src/main.rs b/sz-poc-offsite-2025/evm/evm-node/src/main.rs new file mode 100644 index 0000000..d1f3656 --- /dev/null +++ b/sz-poc-offsite-2025/evm/evm-node/src/main.rs @@ -0,0 +1,34 @@ +use clap::Parser; +use futures_util::StreamExt; +use reth::{ + builder::NodeHandle, chainspec::EthereumChainSpecParser, cli::Cli, + transaction_pool::TransactionPool, +}; +use reth_cli_commands::node::NoArgs; +use reth_node_ethereum::node::EthereumNode; + +fn main() { + Cli::::parse() + .run(|builder, _| async move { + // launch the node + let NodeHandle { + node, + node_exit_future, + } = builder.node(EthereumNode::default()).launch().await?; + + // create a new subscription to pending transactions + let mut pending_transactions = node.pool.new_pending_pool_transactions_listener(); + + // Spawn an async block to listen for validated transactions. + node.task_executor.spawn(Box::pin(async move { + // Waiting for new transactions + while let Some(event) = pending_transactions.next().await { + let tx = event.transaction; + println!("Transaction received: {:?}", tx.transaction); + } + })); + + node_exit_future.await + }) + .unwrap(); +} diff --git a/sz-poc-offsite-2025/node/Cargo.toml b/sz-poc-offsite-2025/node/Cargo.toml deleted file mode 100644 index cfdc2e1..0000000 --- a/sz-poc-offsite-2025/node/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "node" -edition = { workspace = true } - -[dependencies] -tokio = { workspace = true, features = ["full"] } diff --git a/sz-poc-offsite-2025/node/src/main.rs b/sz-poc-offsite-2025/node/src/main.rs deleted file mode 100644 index 7f755fb..0000000 --- a/sz-poc-offsite-2025/node/src/main.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[tokio::main] -async fn main() {} From 25cd9c9a52d63625c75714b8c310e9aad506eb52 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 9 Apr 2025 10:13:25 +0200 Subject: [PATCH 04/11] Skelton complete --- sz-poc-offsite-2025/Cargo.toml | 7 +- sz-poc-offsite-2025/evm/evm-node/src/main.rs | 34 -- .../evm/{evm-node => node}/Cargo.toml | 2 + sz-poc-offsite-2025/evm/node/src/main.rs | 26 ++ .../evm/sequencer-mempool/Cargo.toml | 9 + .../evm/sequencer-mempool/src/lib.rs | 365 ++++++++++++++++++ 6 files changed, 407 insertions(+), 36 deletions(-) delete mode 100644 sz-poc-offsite-2025/evm/evm-node/src/main.rs rename sz-poc-offsite-2025/evm/{evm-node => node}/Cargo.toml (86%) create mode 100644 sz-poc-offsite-2025/evm/node/src/main.rs create mode 100644 sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml create mode 100644 sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml index e4f16ed..4b21ae4 100644 --- a/sz-poc-offsite-2025/Cargo.toml +++ b/sz-poc-offsite-2025/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["evm/evm-node"] +members = ["evm/node", "evm/sequencer-mempool"] resolver = "3" [workspace.package] @@ -7,12 +7,15 @@ edition = "2024" [workspace.dependencies] # Internal -evm-node = { path = "evm/evm-node" } +evm-node = { path = "evm/node" } +evm-sequencer-mempool = { path = "evm/sequencer-mempool" } # External clap = { version = "4.5" } +eyre = { version = "0.6" } futures-util = { version = "0.3" } jsonrpsee = { version = "0.24" } reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } reth-cli-commands = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } +tokio = { version = "1.0" } diff --git a/sz-poc-offsite-2025/evm/evm-node/src/main.rs b/sz-poc-offsite-2025/evm/evm-node/src/main.rs deleted file mode 100644 index d1f3656..0000000 --- a/sz-poc-offsite-2025/evm/evm-node/src/main.rs +++ /dev/null @@ -1,34 +0,0 @@ -use clap::Parser; -use futures_util::StreamExt; -use reth::{ - builder::NodeHandle, chainspec::EthereumChainSpecParser, cli::Cli, - transaction_pool::TransactionPool, -}; -use reth_cli_commands::node::NoArgs; -use reth_node_ethereum::node::EthereumNode; - -fn main() { - Cli::::parse() - .run(|builder, _| async move { - // launch the node - let NodeHandle { - node, - node_exit_future, - } = builder.node(EthereumNode::default()).launch().await?; - - // create a new subscription to pending transactions - let mut pending_transactions = node.pool.new_pending_pool_transactions_listener(); - - // Spawn an async block to listen for validated transactions. - node.task_executor.spawn(Box::pin(async move { - // Waiting for new transactions - while let Some(event) = pending_transactions.next().await { - let tx = event.transaction; - println!("Transaction received: {:?}", tx.transaction); - } - })); - - node_exit_future.await - }) - .unwrap(); -} diff --git a/sz-poc-offsite-2025/evm/evm-node/Cargo.toml b/sz-poc-offsite-2025/evm/node/Cargo.toml similarity index 86% rename from sz-poc-offsite-2025/evm/evm-node/Cargo.toml rename to sz-poc-offsite-2025/evm/node/Cargo.toml index b67508d..2321a85 100644 --- a/sz-poc-offsite-2025/evm/evm-node/Cargo.toml +++ b/sz-poc-offsite-2025/evm/node/Cargo.toml @@ -3,6 +3,8 @@ name = "evm-node" edition = { workspace = true } [dependencies] +evm-sequencer-mempool = { workspace = true } + clap = { workspace = true } futures-util = { workspace = true } jsonrpsee = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/node/src/main.rs b/sz-poc-offsite-2025/evm/node/src/main.rs new file mode 100644 index 0000000..46f7a98 --- /dev/null +++ b/sz-poc-offsite-2025/evm/node/src/main.rs @@ -0,0 +1,26 @@ +use reth::cli::Cli; +use reth_node_ethereum::node::{EthereumAddOns, EthereumNode}; + +use evm_sequencer_mempool::EvmSequencerMempoolBuilder; + +fn main() { + Cli::parse_args() + .run(|builder, _| async move { + // launch the node + let handle = Box::pin( + builder + // use the default ethereum node types + .with_types::() + // use default ethereum components but use our custom pool + .with_components( + EthereumNode::components().pool(EvmSequencerMempoolBuilder::default()), + ) + .with_add_ons(EthereumAddOns::default()) + .launch(), + ) + .await?; + + handle.wait_for_node_exit().await + }) + .unwrap(); +} diff --git a/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml new file mode 100644 index 0000000..4bc60c6 --- /dev/null +++ b/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "evm-sequencer-mempool" +edition = { workspace = true } + +[dependencies] +eyre = { workspace = true } +reth = { workspace = true } +reth-node-ethereum = { workspace = true } +tokio = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs b/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs new file mode 100644 index 0000000..3f06fab --- /dev/null +++ b/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs @@ -0,0 +1,365 @@ +use std::{collections::HashSet, sync::Arc}; +use tokio::sync::mpsc::Receiver; + +use reth::{ + api::{Block, FullNodeTypes, NodeTypes}, + builder::{BuilderContext, components::PoolBuilder}, + chainspec::ChainSpec, + network::types::HandleMempoolData, + primitives::{EthPrimitives, Recovered}, + providers::ChangedAccount, + revm::primitives::{Address, B256, alloy_primitives::TxHash}, + rpc::types::{BlobTransactionSidecar, engine::BlobAndProofV1}, + transaction_pool::{ + AllPoolTransactions, AllTransactionsEvents, BestTransactions, BestTransactionsAttributes, + BlobStore, BlobStoreError, BlockInfo, CanonicalStateUpdate, CoinbaseTipOrdering, + EthPoolTransaction, EthPooledTransaction, EthTransactionValidator, + GetPooledTransactionLimit, NewBlobSidecar, NewTransactionEvent, Pool, PoolResult, PoolSize, + PoolTransaction, PropagatedTransactions, TransactionEvents, TransactionListenerKind, + TransactionOrdering, TransactionOrigin, TransactionPool, TransactionPoolExt, + TransactionValidationTaskExecutor, TransactionValidator, ValidPoolTransaction, + blobstore::DiskFileBlobStore, + }, +}; +use reth_node_ethereum::node::EthereumPoolBuilder; + +#[derive(Default)] +pub struct EvmSequencerMempoolBuilder(EthereumPoolBuilder); + +impl PoolBuilder for EvmSequencerMempoolBuilder +where + Types: NodeTypes, + Node: FullNodeTypes, +{ + type Pool = EvmSequencerMempool; + + async fn build_pool(self, ctx: &BuilderContext) -> eyre::Result { + let pool = self.0.build_pool(ctx).await?; + Ok(EvmSequencerPool(pool)) + } +} + +pub type EvmSequencerMempool = EvmSequencerPool< + TransactionValidationTaskExecutor>, + CoinbaseTipOrdering, + S, +>; + +#[derive(Debug)] +pub struct EvmSequencerPool(Pool) +where + T: TransactionOrdering; + +impl TransactionPool for EvmSequencerPool +where + V: TransactionValidator, + ::Transaction: EthPoolTransaction, + T: TransactionOrdering::Transaction>, + S: BlobStore, +{ + type Transaction = T::Transaction; + + fn pool_size(&self) -> PoolSize { + self.0.pool_size() + } + + fn block_info(&self) -> BlockInfo { + self.0.block_info() + } + + fn add_transaction_and_subscribe( + &self, + origin: TransactionOrigin, + transaction: Self::Transaction, + ) -> impl Future> + Send { + self.0.add_transaction_and_subscribe(origin, transaction) + } + + fn add_transaction( + &self, + origin: TransactionOrigin, + transaction: Self::Transaction, + ) -> impl Future> + Send { + self.0.add_transaction(origin, transaction) + } + + fn add_transactions( + &self, + origin: TransactionOrigin, + transactions: Vec, + ) -> impl Future>> + Send { + self.0.add_transactions(origin, transactions) + } + + fn transaction_event_listener(&self, tx_hash: TxHash) -> Option { + self.0.transaction_event_listener(tx_hash) + } + + fn all_transactions_event_listener(&self) -> AllTransactionsEvents { + self.0.all_transactions_event_listener() + } + + fn pending_transactions_listener_for(&self, kind: TransactionListenerKind) -> Receiver { + self.0.pending_transactions_listener_for(kind) + } + + fn blob_transaction_sidecars_listener(&self) -> Receiver { + self.0.blob_transaction_sidecars_listener() + } + + fn new_transactions_listener_for( + &self, + kind: TransactionListenerKind, + ) -> Receiver> { + self.0.new_transactions_listener_for(kind) + } + + fn pooled_transaction_hashes(&self) -> Vec { + self.0.pooled_transaction_hashes() + } + + fn pooled_transaction_hashes_max(&self, max: usize) -> Vec { + self.0.pooled_transaction_hashes_max(max) + } + + fn pooled_transactions(&self) -> Vec>> { + self.0.pooled_transactions() + } + + fn pooled_transactions_max( + &self, + max: usize, + ) -> Vec>> { + self.0.pooled_transactions_max(max) + } + + fn get_pooled_transaction_elements( + &self, + tx_hashes: Vec, + limit: GetPooledTransactionLimit, + ) -> Vec<::Pooled> { + self.0.get_pooled_transaction_elements(tx_hashes, limit) + } + + fn get_pooled_transaction_element( + &self, + tx_hash: TxHash, + ) -> Option::Pooled>> { + self.0.get_pooled_transaction_element(tx_hash) + } + + fn best_transactions( + &self, + ) -> Box>>> { + self.0.best_transactions() + } + + fn best_transactions_with_attributes( + &self, + best_transactions_attributes: BestTransactionsAttributes, + ) -> Box>>> { + self.0 + .best_transactions_with_attributes(best_transactions_attributes) + } + + fn pending_transactions(&self) -> Vec>> { + self.0.pending_transactions() + } + + fn pending_transactions_max( + &self, + max: usize, + ) -> Vec>> { + self.0.pending_transactions_max(max) + } + + fn queued_transactions(&self) -> Vec>> { + self.0.queued_transactions() + } + + fn all_transactions(&self) -> AllPoolTransactions { + self.0.all_transactions() + } + + fn remove_transactions( + &self, + hashes: Vec, + ) -> Vec>> { + self.0.remove_transactions(hashes) + } + + fn remove_transactions_and_descendants( + &self, + hashes: Vec, + ) -> Vec>> { + self.0.remove_transactions_and_descendants(hashes) + } + + fn remove_transactions_by_sender( + &self, + sender: Address, + ) -> Vec>> { + self.0.remove_transactions_by_sender(sender) + } + + fn retain_unknown(&self, announcement: &mut A) + where + A: HandleMempoolData, + { + self.0.retain_unknown(announcement); + } + + fn get(&self, tx_hash: &TxHash) -> Option>> { + self.0.get(tx_hash) + } + + fn get_all(&self, txs: Vec) -> Vec>> { + self.0.get_all(txs) + } + + fn on_propagated(&self, txs: PropagatedTransactions) { + self.0.on_propagated(txs); + } + + fn get_transactions_by_sender( + &self, + sender: Address, + ) -> Vec>> { + self.0.get_transactions_by_sender(sender) + } + + fn get_pending_transactions_with_predicate( + &self, + predicate: impl FnMut(&ValidPoolTransaction) -> bool, + ) -> Vec>> { + self.0.get_pending_transactions_with_predicate(predicate) + } + + fn get_pending_transactions_by_sender( + &self, + sender: Address, + ) -> Vec>> { + self.0.get_pending_transactions_by_sender(sender) + } + + fn get_queued_transactions_by_sender( + &self, + sender: Address, + ) -> Vec>> { + self.0.get_queued_transactions_by_sender(sender) + } + + fn get_highest_transaction_by_sender( + &self, + sender: Address, + ) -> Option>> { + self.0.get_highest_transaction_by_sender(sender) + } + + fn get_highest_consecutive_transaction_by_sender( + &self, + sender: Address, + on_chain_nonce: u64, + ) -> Option>> { + self.0 + .get_highest_consecutive_transaction_by_sender(sender, on_chain_nonce) + } + + fn get_transaction_by_sender_and_nonce( + &self, + sender: Address, + nonce: u64, + ) -> Option>> { + self.0.get_transaction_by_sender_and_nonce(sender, nonce) + } + + fn get_transactions_by_origin( + &self, + origin: TransactionOrigin, + ) -> Vec>> { + self.0.get_transactions_by_origin(origin) + } + + fn get_pending_transactions_by_origin( + &self, + origin: TransactionOrigin, + ) -> Vec>> { + self.0.get_pending_transactions_by_origin(origin) + } + + fn unique_senders(&self) -> HashSet
{ + self.0.unique_senders() + } + + fn get_blob( + &self, + tx_hash: TxHash, + ) -> Result>, BlobStoreError> { + self.0.get_blob(tx_hash) + } + + fn get_all_blobs( + &self, + tx_hashes: Vec, + ) -> Result)>, BlobStoreError> { + self.0.get_all_blobs(tx_hashes) + } + + fn get_all_blobs_exact( + &self, + tx_hashes: Vec, + ) -> Result>, BlobStoreError> { + self.0.get_all_blobs_exact(tx_hashes) + } + + fn get_blobs_for_versioned_hashes( + &self, + versioned_hashes: &[B256], + ) -> Result>, BlobStoreError> { + self.0.get_blobs_for_versioned_hashes(versioned_hashes) + } +} + +impl TransactionPoolExt for EvmSequencerPool +where + V: TransactionValidator, + ::Transaction: EthPoolTransaction, + T: TransactionOrdering::Transaction>, + S: BlobStore, +{ + fn set_block_info(&self, info: BlockInfo) { + self.0.set_block_info(info); + } + + fn on_canonical_state_change(&self, update: CanonicalStateUpdate<'_, B>) + where + B: Block, + { + self.0.on_canonical_state_change(update); + } + + fn update_accounts(&self, accounts: Vec) { + self.0.update_accounts(accounts); + } + + fn delete_blob(&self, tx: TxHash) { + self.0.delete_blob(tx); + } + + fn delete_blobs(&self, txs: Vec) { + self.0.delete_blobs(txs); + } + + fn cleanup_blobs(&self) { + self.0.cleanup_blobs(); + } +} + +impl Clone for EvmSequencerPool +where + T: TransactionOrdering, +{ + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} From 577eb2313f60437279b79875db10e3e98a3c0b6a Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 9 Apr 2025 13:06:47 +0200 Subject: [PATCH 05/11] Restructure project namign --- sz-poc-offsite-2025/Cargo.toml | 4 ++-- sz-poc-offsite-2025/evm/{node => sequencer-node}/Cargo.toml | 2 +- sz-poc-offsite-2025/evm/{node => sequencer-node}/src/main.rs | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename sz-poc-offsite-2025/evm/{node => sequencer-node}/Cargo.toml (91%) rename sz-poc-offsite-2025/evm/{node => sequencer-node}/src/main.rs (100%) diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml index 4b21ae4..4fa61ad 100644 --- a/sz-poc-offsite-2025/Cargo.toml +++ b/sz-poc-offsite-2025/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["evm/node", "evm/sequencer-mempool"] +members = ["evm/sequencer-node", "evm/sequencer-mempool"] resolver = "3" [workspace.package] @@ -7,7 +7,7 @@ edition = "2024" [workspace.dependencies] # Internal -evm-node = { path = "evm/node" } +evm-sequencer-node = { path = "evm/sequencer-node" } evm-sequencer-mempool = { path = "evm/sequencer-mempool" } # External diff --git a/sz-poc-offsite-2025/evm/node/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml similarity index 91% rename from sz-poc-offsite-2025/evm/node/Cargo.toml rename to sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml index 2321a85..21ac0cc 100644 --- a/sz-poc-offsite-2025/evm/node/Cargo.toml +++ b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "evm-node" +name = "evm-sequencer-node" edition = { workspace = true } [dependencies] diff --git a/sz-poc-offsite-2025/evm/node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs similarity index 100% rename from sz-poc-offsite-2025/evm/node/src/main.rs rename to sz-poc-offsite-2025/evm/sequencer-node/src/main.rs From 3c937cddc9486a19d052678de36e5076fb81d6c8 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 9 Apr 2025 14:15:35 +0200 Subject: [PATCH 06/11] WIP --- sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml | 5 +++++ sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs | 0 2 files changed, 5 insertions(+) create mode 100644 sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml create mode 100644 sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs diff --git a/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml new file mode 100644 index 0000000..c9ef4f2 --- /dev/null +++ b/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "evm-sequencer-batcher" +edition = { workspace = true } + +[dependencies] diff --git a/sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs b/sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs new file mode 100644 index 0000000..e69de29 From 894249fa4deae3333a491d20fc985172e5cf7b72 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 9 Apr 2025 16:22:26 +0200 Subject: [PATCH 07/11] Implement custom extension to listen to chain events --- sz-poc-offsite-2025/Cargo.toml | 12 +- .../evm/sequencer-batcher/Cargo.toml | 5 - .../evm/sequencer-batcher/src/lib.rs | 0 .../evm/sequencer-mempool/Cargo.toml | 9 - .../evm/sequencer-mempool/src/lib.rs | 365 ------------------ .../evm/sequencer-node/Cargo.toml | 11 +- .../evm/sequencer-node/src/main.rs | 54 ++- 7 files changed, 48 insertions(+), 408 deletions(-) delete mode 100644 sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml delete mode 100644 sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs delete mode 100644 sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml delete mode 100644 sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml index 4fa61ad..759223f 100644 --- a/sz-poc-offsite-2025/Cargo.toml +++ b/sz-poc-offsite-2025/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["evm/sequencer-node", "evm/sequencer-mempool"] +members = ["evm/sequencer-node"] resolver = "3" [workspace.package] @@ -8,14 +8,10 @@ edition = "2024" [workspace.dependencies] # Internal evm-sequencer-node = { path = "evm/sequencer-node" } -evm-sequencer-mempool = { path = "evm/sequencer-mempool" } # External -clap = { version = "4.5" } eyre = { version = "0.6" } -futures-util = { version = "0.3" } -jsonrpsee = { version = "0.24" } +futures = { version = "0.3" } reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } -reth-cli-commands = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } -reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } -tokio = { version = "1.0" } +reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } +reth-tracing = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } diff --git a/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml deleted file mode 100644 index c9ef4f2..0000000 --- a/sz-poc-offsite-2025/evm/sequencer-batcher/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[package] -name = "evm-sequencer-batcher" -edition = { workspace = true } - -[dependencies] diff --git a/sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs b/sz-poc-offsite-2025/evm/sequencer-batcher/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml deleted file mode 100644 index 4bc60c6..0000000 --- a/sz-poc-offsite-2025/evm/sequencer-mempool/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "evm-sequencer-mempool" -edition = { workspace = true } - -[dependencies] -eyre = { workspace = true } -reth = { workspace = true } -reth-node-ethereum = { workspace = true } -tokio = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs b/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs deleted file mode 100644 index 3f06fab..0000000 --- a/sz-poc-offsite-2025/evm/sequencer-mempool/src/lib.rs +++ /dev/null @@ -1,365 +0,0 @@ -use std::{collections::HashSet, sync::Arc}; -use tokio::sync::mpsc::Receiver; - -use reth::{ - api::{Block, FullNodeTypes, NodeTypes}, - builder::{BuilderContext, components::PoolBuilder}, - chainspec::ChainSpec, - network::types::HandleMempoolData, - primitives::{EthPrimitives, Recovered}, - providers::ChangedAccount, - revm::primitives::{Address, B256, alloy_primitives::TxHash}, - rpc::types::{BlobTransactionSidecar, engine::BlobAndProofV1}, - transaction_pool::{ - AllPoolTransactions, AllTransactionsEvents, BestTransactions, BestTransactionsAttributes, - BlobStore, BlobStoreError, BlockInfo, CanonicalStateUpdate, CoinbaseTipOrdering, - EthPoolTransaction, EthPooledTransaction, EthTransactionValidator, - GetPooledTransactionLimit, NewBlobSidecar, NewTransactionEvent, Pool, PoolResult, PoolSize, - PoolTransaction, PropagatedTransactions, TransactionEvents, TransactionListenerKind, - TransactionOrdering, TransactionOrigin, TransactionPool, TransactionPoolExt, - TransactionValidationTaskExecutor, TransactionValidator, ValidPoolTransaction, - blobstore::DiskFileBlobStore, - }, -}; -use reth_node_ethereum::node::EthereumPoolBuilder; - -#[derive(Default)] -pub struct EvmSequencerMempoolBuilder(EthereumPoolBuilder); - -impl PoolBuilder for EvmSequencerMempoolBuilder -where - Types: NodeTypes, - Node: FullNodeTypes, -{ - type Pool = EvmSequencerMempool; - - async fn build_pool(self, ctx: &BuilderContext) -> eyre::Result { - let pool = self.0.build_pool(ctx).await?; - Ok(EvmSequencerPool(pool)) - } -} - -pub type EvmSequencerMempool = EvmSequencerPool< - TransactionValidationTaskExecutor>, - CoinbaseTipOrdering, - S, ->; - -#[derive(Debug)] -pub struct EvmSequencerPool(Pool) -where - T: TransactionOrdering; - -impl TransactionPool for EvmSequencerPool -where - V: TransactionValidator, - ::Transaction: EthPoolTransaction, - T: TransactionOrdering::Transaction>, - S: BlobStore, -{ - type Transaction = T::Transaction; - - fn pool_size(&self) -> PoolSize { - self.0.pool_size() - } - - fn block_info(&self) -> BlockInfo { - self.0.block_info() - } - - fn add_transaction_and_subscribe( - &self, - origin: TransactionOrigin, - transaction: Self::Transaction, - ) -> impl Future> + Send { - self.0.add_transaction_and_subscribe(origin, transaction) - } - - fn add_transaction( - &self, - origin: TransactionOrigin, - transaction: Self::Transaction, - ) -> impl Future> + Send { - self.0.add_transaction(origin, transaction) - } - - fn add_transactions( - &self, - origin: TransactionOrigin, - transactions: Vec, - ) -> impl Future>> + Send { - self.0.add_transactions(origin, transactions) - } - - fn transaction_event_listener(&self, tx_hash: TxHash) -> Option { - self.0.transaction_event_listener(tx_hash) - } - - fn all_transactions_event_listener(&self) -> AllTransactionsEvents { - self.0.all_transactions_event_listener() - } - - fn pending_transactions_listener_for(&self, kind: TransactionListenerKind) -> Receiver { - self.0.pending_transactions_listener_for(kind) - } - - fn blob_transaction_sidecars_listener(&self) -> Receiver { - self.0.blob_transaction_sidecars_listener() - } - - fn new_transactions_listener_for( - &self, - kind: TransactionListenerKind, - ) -> Receiver> { - self.0.new_transactions_listener_for(kind) - } - - fn pooled_transaction_hashes(&self) -> Vec { - self.0.pooled_transaction_hashes() - } - - fn pooled_transaction_hashes_max(&self, max: usize) -> Vec { - self.0.pooled_transaction_hashes_max(max) - } - - fn pooled_transactions(&self) -> Vec>> { - self.0.pooled_transactions() - } - - fn pooled_transactions_max( - &self, - max: usize, - ) -> Vec>> { - self.0.pooled_transactions_max(max) - } - - fn get_pooled_transaction_elements( - &self, - tx_hashes: Vec, - limit: GetPooledTransactionLimit, - ) -> Vec<::Pooled> { - self.0.get_pooled_transaction_elements(tx_hashes, limit) - } - - fn get_pooled_transaction_element( - &self, - tx_hash: TxHash, - ) -> Option::Pooled>> { - self.0.get_pooled_transaction_element(tx_hash) - } - - fn best_transactions( - &self, - ) -> Box>>> { - self.0.best_transactions() - } - - fn best_transactions_with_attributes( - &self, - best_transactions_attributes: BestTransactionsAttributes, - ) -> Box>>> { - self.0 - .best_transactions_with_attributes(best_transactions_attributes) - } - - fn pending_transactions(&self) -> Vec>> { - self.0.pending_transactions() - } - - fn pending_transactions_max( - &self, - max: usize, - ) -> Vec>> { - self.0.pending_transactions_max(max) - } - - fn queued_transactions(&self) -> Vec>> { - self.0.queued_transactions() - } - - fn all_transactions(&self) -> AllPoolTransactions { - self.0.all_transactions() - } - - fn remove_transactions( - &self, - hashes: Vec, - ) -> Vec>> { - self.0.remove_transactions(hashes) - } - - fn remove_transactions_and_descendants( - &self, - hashes: Vec, - ) -> Vec>> { - self.0.remove_transactions_and_descendants(hashes) - } - - fn remove_transactions_by_sender( - &self, - sender: Address, - ) -> Vec>> { - self.0.remove_transactions_by_sender(sender) - } - - fn retain_unknown(&self, announcement: &mut A) - where - A: HandleMempoolData, - { - self.0.retain_unknown(announcement); - } - - fn get(&self, tx_hash: &TxHash) -> Option>> { - self.0.get(tx_hash) - } - - fn get_all(&self, txs: Vec) -> Vec>> { - self.0.get_all(txs) - } - - fn on_propagated(&self, txs: PropagatedTransactions) { - self.0.on_propagated(txs); - } - - fn get_transactions_by_sender( - &self, - sender: Address, - ) -> Vec>> { - self.0.get_transactions_by_sender(sender) - } - - fn get_pending_transactions_with_predicate( - &self, - predicate: impl FnMut(&ValidPoolTransaction) -> bool, - ) -> Vec>> { - self.0.get_pending_transactions_with_predicate(predicate) - } - - fn get_pending_transactions_by_sender( - &self, - sender: Address, - ) -> Vec>> { - self.0.get_pending_transactions_by_sender(sender) - } - - fn get_queued_transactions_by_sender( - &self, - sender: Address, - ) -> Vec>> { - self.0.get_queued_transactions_by_sender(sender) - } - - fn get_highest_transaction_by_sender( - &self, - sender: Address, - ) -> Option>> { - self.0.get_highest_transaction_by_sender(sender) - } - - fn get_highest_consecutive_transaction_by_sender( - &self, - sender: Address, - on_chain_nonce: u64, - ) -> Option>> { - self.0 - .get_highest_consecutive_transaction_by_sender(sender, on_chain_nonce) - } - - fn get_transaction_by_sender_and_nonce( - &self, - sender: Address, - nonce: u64, - ) -> Option>> { - self.0.get_transaction_by_sender_and_nonce(sender, nonce) - } - - fn get_transactions_by_origin( - &self, - origin: TransactionOrigin, - ) -> Vec>> { - self.0.get_transactions_by_origin(origin) - } - - fn get_pending_transactions_by_origin( - &self, - origin: TransactionOrigin, - ) -> Vec>> { - self.0.get_pending_transactions_by_origin(origin) - } - - fn unique_senders(&self) -> HashSet
{ - self.0.unique_senders() - } - - fn get_blob( - &self, - tx_hash: TxHash, - ) -> Result>, BlobStoreError> { - self.0.get_blob(tx_hash) - } - - fn get_all_blobs( - &self, - tx_hashes: Vec, - ) -> Result)>, BlobStoreError> { - self.0.get_all_blobs(tx_hashes) - } - - fn get_all_blobs_exact( - &self, - tx_hashes: Vec, - ) -> Result>, BlobStoreError> { - self.0.get_all_blobs_exact(tx_hashes) - } - - fn get_blobs_for_versioned_hashes( - &self, - versioned_hashes: &[B256], - ) -> Result>, BlobStoreError> { - self.0.get_blobs_for_versioned_hashes(versioned_hashes) - } -} - -impl TransactionPoolExt for EvmSequencerPool -where - V: TransactionValidator, - ::Transaction: EthPoolTransaction, - T: TransactionOrdering::Transaction>, - S: BlobStore, -{ - fn set_block_info(&self, info: BlockInfo) { - self.0.set_block_info(info); - } - - fn on_canonical_state_change(&self, update: CanonicalStateUpdate<'_, B>) - where - B: Block, - { - self.0.on_canonical_state_change(update); - } - - fn update_accounts(&self, accounts: Vec) { - self.0.update_accounts(accounts); - } - - fn delete_blob(&self, tx: TxHash) { - self.0.delete_blob(tx); - } - - fn delete_blobs(&self, txs: Vec) { - self.0.delete_blobs(txs); - } - - fn cleanup_blobs(&self) { - self.0.cleanup_blobs(); - } -} - -impl Clone for EvmSequencerPool -where - T: TransactionOrdering, -{ - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} diff --git a/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml index 21ac0cc..2fd69f3 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml +++ b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml @@ -3,11 +3,8 @@ name = "evm-sequencer-node" edition = { workspace = true } [dependencies] -evm-sequencer-mempool = { workspace = true } - -clap = { workspace = true } -futures-util = { workspace = true } -jsonrpsee = { workspace = true } +eyre = { workspace = true } +futures = { workspace = true } reth = { workspace = true } -reth-cli-commands = { workspace = true } -reth-node-ethereum = { workspace = true } +reth-ethereum = { workspace = true, features = ["full"] } +reth-tracing = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs index 46f7a98..692447d 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs +++ b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs @@ -1,26 +1,52 @@ +use futures::TryStreamExt as _; use reth::cli::Cli; -use reth_node_ethereum::node::{EthereumAddOns, EthereumNode}; +use reth_ethereum::{ + exex::{ExExContext, ExExEvent, ExExNotification}, + node::{EthereumNode, api::FullNodeComponents}, +}; +use reth_tracing::tracing::info; -use evm_sequencer_mempool::EvmSequencerMempoolBuilder; +async fn push_block_to_da( + mut ctx: ExExContext, +) -> eyre::Result<()> { + while let Some(notification) = ctx.notifications.try_next().await? { + match ¬ification { + ExExNotification::ChainCommitted { new } => { + // TODO: Push range of finalized blocks to DA, and interact with prover to generate a proof over the range. + info!(committed_chain = ?new.range(), "Received commit"); + } + ExExNotification::ChainReorged { old, new } => { + info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg"); + } + ExExNotification::ChainReverted { old } => { + info!(reverted_chain = ?old.range(), "Received revert"); + } + }; -fn main() { - Cli::parse_args() - .run(|builder, _| async move { - // launch the node + if let Some(committed_chain) = notification.committed_chain() { + ctx.events + .send(ExExEvent::FinishedHeight(committed_chain.tip().num_hash())) + .unwrap(); + } + } + + Ok(()) +} + +fn main() -> eyre::Result<()> { + Cli::parse_args().run(|builder, _| { + Box::pin(async move { let handle = Box::pin( builder - // use the default ethereum node types - .with_types::() - // use default ethereum components but use our custom pool - .with_components( - EthereumNode::components().pool(EvmSequencerMempoolBuilder::default()), - ) - .with_add_ons(EthereumAddOns::default()) + .node(EthereumNode::default()) + .install_exex("push-block-to-da", async move |ctx| { + Ok(push_block_to_da(ctx)) + }) .launch(), ) .await?; handle.wait_for_node_exit().await }) - .unwrap(); + }) } From 5c5ef74c73d7458e6fac78c903dacbc2dfbe068c Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 10 Apr 2025 09:08:02 +0200 Subject: [PATCH 08/11] Add aggregator --- sz-poc-offsite-2025/Cargo.toml | 4 +- sz-poc-offsite-2025/evm/aggregator/Cargo.toml | 6 +++ sz-poc-offsite-2025/evm/aggregator/src/lib.rs | 15 ++++++++ .../evm/sequencer-node/Cargo.toml | 4 ++ .../evm/sequencer-node/src/main.rs | 38 +++++++++++-------- 5 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 sz-poc-offsite-2025/evm/aggregator/Cargo.toml create mode 100644 sz-poc-offsite-2025/evm/aggregator/src/lib.rs diff --git a/sz-poc-offsite-2025/Cargo.toml b/sz-poc-offsite-2025/Cargo.toml index 759223f..9e9d834 100644 --- a/sz-poc-offsite-2025/Cargo.toml +++ b/sz-poc-offsite-2025/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["evm/sequencer-node"] +members = ["evm/aggregator", "evm/sequencer-node"] resolver = "3" [workspace.package] @@ -7,6 +7,7 @@ edition = "2024" [workspace.dependencies] # Internal +evm-aggregator = { path = "evm/aggregator" } evm-sequencer-node = { path = "evm/sequencer-node" } # External @@ -14,4 +15,5 @@ eyre = { version = "0.6" } futures = { version = "0.3" } reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } +reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } reth-tracing = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } diff --git a/sz-poc-offsite-2025/evm/aggregator/Cargo.toml b/sz-poc-offsite-2025/evm/aggregator/Cargo.toml new file mode 100644 index 0000000..4cf5bf8 --- /dev/null +++ b/sz-poc-offsite-2025/evm/aggregator/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "evm-aggregator" +edition = { workspace = true } + +[dependencies] +reth-ethereum = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/aggregator/src/lib.rs b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs new file mode 100644 index 0000000..41a5d8f --- /dev/null +++ b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs @@ -0,0 +1,15 @@ +// TODO: The logic to batch multiple of these blocks (or the transactions within them) and send them to DA and generate proofs is still missing. It will have to be added at the offsite. +// This type does not support any recovery mechanism, so if the node is stopped, the state DB should be cleaned before starting again. +#[derive(Default)] +pub struct Aggregator { + unprocessed_blocks: Vec, +} + +impl Aggregator +where + Block: reth_ethereum::primitives::Block, +{ + pub fn process_blocks(&mut self, new_blocks: impl Iterator) { + self.unprocessed_blocks.extend(new_blocks); + } +} diff --git a/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml index 2fd69f3..e76b274 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml +++ b/sz-poc-offsite-2025/evm/sequencer-node/Cargo.toml @@ -3,8 +3,12 @@ name = "evm-sequencer-node" edition = { workspace = true } [dependencies] + +evm-aggregator = { workspace = true } + eyre = { workspace = true } futures = { workspace = true } reth = { workspace = true } reth-ethereum = { workspace = true, features = ["full"] } +reth-ethereum-primitives = { workspace = true } reth-tracing = { workspace = true } diff --git a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs index 692447d..7c6ae7f 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs +++ b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs @@ -1,27 +1,34 @@ +use evm_aggregator::Aggregator; use futures::TryStreamExt as _; -use reth::cli::Cli; +use reth::{ + api::{FullNodeTypes, NodePrimitives, NodeTypes}, + cli::Cli, +}; use reth_ethereum::{ exex::{ExExContext, ExExEvent, ExExNotification}, node::{EthereumNode, api::FullNodeComponents}, }; use reth_tracing::tracing::info; -async fn push_block_to_da( +pub type Block = + <<::Types as NodeTypes>::Primitives as NodePrimitives>::Block; + +async fn aggregate_block_txs( mut ctx: ExExContext, + mut aggregator: Aggregator>, ) -> eyre::Result<()> { while let Some(notification) = ctx.notifications.try_next().await? { - match ¬ification { - ExExNotification::ChainCommitted { new } => { - // TODO: Push range of finalized blocks to DA, and interact with prover to generate a proof over the range. - info!(committed_chain = ?new.range(), "Received commit"); - } - ExExNotification::ChainReorged { old, new } => { - info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg"); - } - ExExNotification::ChainReverted { old } => { - info!(reverted_chain = ?old.range(), "Received revert"); - } + let ExExNotification::ChainCommitted { new } = ¬ification else { + continue; }; + info!(committed_chain = ?new.range(), "Received commit"); + aggregator.process_blocks( + new.inner() + .0 + .clone() + .into_blocks() + .map(reth_ethereum::primitives::RecoveredBlock::into_block), + ); if let Some(committed_chain) = notification.committed_chain() { ctx.events @@ -36,11 +43,12 @@ async fn push_block_to_da( fn main() -> eyre::Result<()> { Cli::parse_args().run(|builder, _| { Box::pin(async move { + let aggregator = Aggregator::default(); let handle = Box::pin( builder .node(EthereumNode::default()) - .install_exex("push-block-to-da", async move |ctx| { - Ok(push_block_to_da(ctx)) + .install_exex("aggregate-block-txs", async move |ctx| { + Ok(aggregate_block_txs(ctx, aggregator)) }) .launch(), ) From 1b04d1a99e2f53b24b2e94311a22ac3b80c7e629 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 10 Apr 2025 09:25:33 +0200 Subject: [PATCH 09/11] Hardcode startup flags --- sz-poc-offsite-2025/evm/aggregator/src/lib.rs | 2 +- sz-poc-offsite-2025/evm/sequencer-node/src/main.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sz-poc-offsite-2025/evm/aggregator/src/lib.rs b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs index 41a5d8f..590be5b 100644 --- a/sz-poc-offsite-2025/evm/aggregator/src/lib.rs +++ b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs @@ -1,5 +1,5 @@ // TODO: The logic to batch multiple of these blocks (or the transactions within them) and send them to DA and generate proofs is still missing. It will have to be added at the offsite. -// This type does not support any recovery mechanism, so if the node is stopped, the state DB should be cleaned before starting again. +// This type does not support any recovery mechanism, so if the node is stopped, the state DB should be cleaned before starting again. The folder is specified by the `--datadir` option in the binary. #[derive(Default)] pub struct Aggregator { unprocessed_blocks: Vec, diff --git a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs index 7c6ae7f..722edf4 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs +++ b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs @@ -41,7 +41,16 @@ async fn aggregate_block_txs( } fn main() -> eyre::Result<()> { - Cli::parse_args().run(|builder, _| { + Cli::try_parse_args_from([ + "reth", + "node", + "--datadir=/tmp/reth-dev/", + "--dev", + "--dev.block-time=2s", + "--http.addr=0.0.0.0", + ]) + .unwrap() + .run(|builder, _| { Box::pin(async move { let aggregator = Aggregator::default(); let handle = Box::pin( From da4d7c12e29b10e79116dd2d510bf5973ccb76b8 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 10 Apr 2025 09:40:15 +0200 Subject: [PATCH 10/11] Hardcode block type to be Ethereum --- sz-poc-offsite-2025/evm/aggregator/src/lib.rs | 9 ++++----- sz-poc-offsite-2025/evm/sequencer-node/src/main.rs | 11 ++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sz-poc-offsite-2025/evm/aggregator/src/lib.rs b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs index 590be5b..27bc9f4 100644 --- a/sz-poc-offsite-2025/evm/aggregator/src/lib.rs +++ b/sz-poc-offsite-2025/evm/aggregator/src/lib.rs @@ -1,14 +1,13 @@ +use reth_ethereum::Block; + // TODO: The logic to batch multiple of these blocks (or the transactions within them) and send them to DA and generate proofs is still missing. It will have to be added at the offsite. // This type does not support any recovery mechanism, so if the node is stopped, the state DB should be cleaned before starting again. The folder is specified by the `--datadir` option in the binary. #[derive(Default)] -pub struct Aggregator { +pub struct Aggregator { unprocessed_blocks: Vec, } -impl Aggregator -where - Block: reth_ethereum::primitives::Block, -{ +impl Aggregator { pub fn process_blocks(&mut self, new_blocks: impl Iterator) { self.unprocessed_blocks.extend(new_blocks); } diff --git a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs index 722edf4..cd4f76f 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs +++ b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs @@ -10,13 +10,14 @@ use reth_ethereum::{ }; use reth_tracing::tracing::info; -pub type Block = - <<::Types as NodeTypes>::Primitives as NodePrimitives>::Block; - async fn aggregate_block_txs( mut ctx: ExExContext, - mut aggregator: Aggregator>, -) -> eyre::Result<()> { + mut aggregator: Aggregator, +) -> eyre::Result<()> +where + <::Types as NodeTypes>::Primitives: + NodePrimitives, +{ while let Some(notification) = ctx.notifications.try_next().await? { let ExExNotification::ChainCommitted { new } = ¬ification else { continue; From 5eb976c9ae4f7446e8688d1a9b49ebbd1e30e959 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 14 Apr 2025 10:38:05 +0200 Subject: [PATCH 11/11] Address PR comment --- sz-poc-offsite-2025/evm/sequencer-node/src/main.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs index cd4f76f..2de08b5 100644 --- a/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs +++ b/sz-poc-offsite-2025/evm/sequencer-node/src/main.rs @@ -31,11 +31,9 @@ where .map(reth_ethereum::primitives::RecoveredBlock::into_block), ); - if let Some(committed_chain) = notification.committed_chain() { - ctx.events - .send(ExExEvent::FinishedHeight(committed_chain.tip().num_hash())) - .unwrap(); - } + ctx.events + .send(ExExEvent::FinishedHeight(new.tip().num_hash())) + .unwrap(); } Ok(())