From 09555c67ac0c95b134ed562b4633d8a50e8b8fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Mon, 23 Jun 2025 14:27:15 +0200 Subject: [PATCH 1/8] copy standard builder to pod --- crates/op-rbuilder/src/builders/pod/mod.rs | 34 + .../op-rbuilder/src/builders/pod/payload.rs | 600 ++++++++++++++++++ 2 files changed, 634 insertions(+) create mode 100644 crates/op-rbuilder/src/builders/pod/mod.rs create mode 100644 crates/op-rbuilder/src/builders/pod/payload.rs diff --git a/crates/op-rbuilder/src/builders/pod/mod.rs b/crates/op-rbuilder/src/builders/pod/mod.rs new file mode 100644 index 00000000..98e9b44f --- /dev/null +++ b/crates/op-rbuilder/src/builders/pod/mod.rs @@ -0,0 +1,34 @@ +use payload::StandardPayloadBuilderBuilder; +use reth_node_builder::components::BasicPayloadServiceBuilder; + +use crate::traits::{NodeBounds, PoolBounds}; + +use super::BuilderConfig; + +mod payload; + +/// Block building strategy that builds blocks using the standard approach by +/// producing blocks every chain block time. +pub struct StandardBuilder; + +impl super::PayloadBuilder for StandardBuilder { + type Config = (); + + type ServiceBuilder + = BasicPayloadServiceBuilder + where + Node: NodeBounds, + Pool: PoolBounds; + + fn new_service( + config: BuilderConfig, + ) -> eyre::Result> + where + Node: NodeBounds, + Pool: PoolBounds, + { + Ok(BasicPayloadServiceBuilder::new( + StandardPayloadBuilderBuilder(config), + )) + } +} diff --git a/crates/op-rbuilder/src/builders/pod/payload.rs b/crates/op-rbuilder/src/builders/pod/payload.rs new file mode 100644 index 00000000..eaf98c2c --- /dev/null +++ b/crates/op-rbuilder/src/builders/pod/payload.rs @@ -0,0 +1,600 @@ +use crate::{ + builders::{generator::BuildArguments, BuilderConfig}, + flashtestations::service::spawn_flashtestations_service, + metrics::OpRBuilderMetrics, + primitives::reth::ExecutionInfo, + traits::{ClientBounds, NodeBounds, PayloadTxsBounds, PoolBounds}, +}; +use alloy_consensus::{ + constants::EMPTY_WITHDRAWALS, proofs, BlockBody, Header, EMPTY_OMMER_ROOT_HASH, +}; +use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; +use alloy_primitives::U256; +use reth::payload::PayloadBuilderAttributes; +use reth_basic_payload_builder::{BuildOutcome, BuildOutcomeKind, MissingPayloadBehaviour}; +use reth_chain_state::{ExecutedBlock, ExecutedBlockWithTrieUpdates, ExecutedTrieUpdates}; +use reth_evm::{execute::BlockBuilder, ConfigureEvm}; +use reth_node_api::{Block, PayloadBuilderError}; +use reth_node_builder::{components::PayloadBuilderBuilder, BuilderContext}; +use reth_optimism_consensus::{calculate_receipt_root_no_memo_optimism, isthmus}; +use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes}; +use reth_optimism_forks::OpHardforks; +use reth_optimism_node::{OpBuiltPayload, OpPayloadBuilderAttributes}; +use reth_optimism_primitives::{OpPrimitives, OpTransactionSigned}; +use reth_payload_util::{BestPayloadTransactions, NoopPayloadTransactions, PayloadTransactions}; +use reth_primitives::RecoveredBlock; +use reth_provider::{ + ExecutionOutcome, HashedPostStateProvider, ProviderError, StateRootProvider, + StorageRootProvider, +}; +use reth_revm::{ + database::StateProviderDatabase, db::states::bundle_state::BundleRetention, State, +}; +use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool}; +use revm::Database; +use std::{sync::Arc, time::Instant}; +use tokio_util::sync::CancellationToken; +use tracing::{error, info, warn}; + +use super::super::context::{estimate_gas_for_builder_tx, OpPayloadBuilderCtx}; + +pub struct StandardPayloadBuilderBuilder(pub BuilderConfig<()>); + +impl PayloadBuilderBuilder for StandardPayloadBuilderBuilder +where + Node: NodeBounds, + Pool: PoolBounds, +{ + type PayloadBuilder = StandardOpPayloadBuilder; + + async fn build_payload_builder( + self, + ctx: &BuilderContext, + pool: Pool, + _evm_config: OpEvmConfig, + ) -> eyre::Result { + let signer = self.0.builder_signer; + + if self.0.flashtestations_config.flashtestations_enabled { + let funding_signer = signer.expect("Key to fund TEE generated address not set"); + match spawn_flashtestations_service( + self.0.flashtestations_config.clone(), + funding_signer, + ctx, + ) + .await + { + Ok(service) => service, + Err(e) => { + tracing::warn!(error = %e, "Failed to spawn flashtestations service, falling back to standard builder tx"); + return Ok(StandardOpPayloadBuilder::new( + OpEvmConfig::optimism(ctx.chain_spec()), + pool, + ctx.provider().clone(), + self.0.clone(), + )); + } + }; + + if self.0.flashtestations_config.enable_block_proofs { + // TODO: flashtestations end of block transaction + } + } + + Ok(StandardOpPayloadBuilder::new( + OpEvmConfig::optimism(ctx.chain_spec()), + pool, + ctx.provider().clone(), + self.0.clone(), + )) + } +} + +/// Optimism's payload builder +#[derive(Debug, Clone)] +pub struct StandardOpPayloadBuilder { + /// The type responsible for creating the evm. + pub evm_config: OpEvmConfig, + /// The transaction pool + pub pool: Pool, + /// Node client + pub client: Client, + /// Settings for the builder, e.g. DA settings. + pub config: BuilderConfig<()>, + /// The type responsible for yielding the best transactions for the payload if mempool + /// transactions are allowed. + pub best_transactions: Txs, + /// The metrics for the builder + pub metrics: Arc, +} + +impl StandardOpPayloadBuilder { + /// `OpPayloadBuilder` constructor. + pub fn new( + evm_config: OpEvmConfig, + pool: Pool, + client: Client, + config: BuilderConfig<()>, + ) -> Self { + Self { + pool, + client, + config, + evm_config, + best_transactions: (), + metrics: Default::default(), + } + } +} + +/// A type that returns a the [`PayloadTransactions`] that should be included in the pool. +pub trait OpPayloadTransactions: Clone + Send + Sync + Unpin + 'static { + /// Returns an iterator that yields the transaction in the order they should get included in the + /// new payload. + fn best_transactions>( + &self, + pool: Pool, + attr: BestTransactionsAttributes, + ) -> impl PayloadTransactions; +} + +impl OpPayloadTransactions for () { + fn best_transactions>( + &self, + pool: Pool, + attr: BestTransactionsAttributes, + ) -> impl PayloadTransactions { + BestPayloadTransactions::new(pool.best_transactions_with_attributes(attr)) + } +} + +impl reth_basic_payload_builder::PayloadBuilder + for StandardOpPayloadBuilder +where + Pool: PoolBounds, + Client: ClientBounds, + Txs: OpPayloadTransactions, +{ + type Attributes = OpPayloadBuilderAttributes; + type BuiltPayload = OpBuiltPayload; + + fn try_build( + &self, + args: reth_basic_payload_builder::BuildArguments, + ) -> Result, PayloadBuilderError> { + let pool = self.pool.clone(); + + let reth_basic_payload_builder::BuildArguments { + cached_reads, + config, + cancel: _, // TODO + best_payload: _, + } = args; + + let args = BuildArguments { + cached_reads, + config, + cancel: CancellationToken::new(), + }; + + self.build_payload(args, |attrs| { + #[allow(clippy::unit_arg)] + self.best_transactions + .best_transactions(pool.clone(), attrs) + }) + } + + fn on_missing_payload( + &self, + _args: reth_basic_payload_builder::BuildArguments, + ) -> MissingPayloadBehaviour { + MissingPayloadBehaviour::AwaitInProgress + } + + fn build_empty_payload( + &self, + config: reth_basic_payload_builder::PayloadConfig< + Self::Attributes, + reth_basic_payload_builder::HeaderForPayload, + >, + ) -> Result { + let args = BuildArguments { + config, + cached_reads: Default::default(), + cancel: Default::default(), + }; + self.build_payload(args, |_| { + NoopPayloadTransactions::::default() + })? + .into_payload() + .ok_or_else(|| PayloadBuilderError::MissingPayload) + } +} + +impl StandardOpPayloadBuilder +where + Pool: PoolBounds, + Client: ClientBounds, +{ + /// Constructs an Optimism payload from the transactions sent via the + /// Payload attributes by the sequencer. If the `no_tx_pool` argument is passed in + /// the payload attributes, the transaction pool will be ignored and the only transactions + /// included in the payload will be those sent through the attributes. + /// + /// Given build arguments including an Optimism client, transaction pool, + /// and configuration, this function creates a transaction payload. Returns + /// a result indicating success with the payload or an error in case of failure. + fn build_payload<'a, Txs: PayloadTxsBounds>( + &self, + args: BuildArguments, OpBuiltPayload>, + best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a, + ) -> Result, PayloadBuilderError> { + let block_build_start_time = Instant::now(); + + let BuildArguments { + mut cached_reads, + config, + cancel, + } = args; + + let chain_spec = self.client.chain_spec(); + let timestamp = config.attributes.timestamp(); + let block_env_attributes = OpNextBlockEnvAttributes { + timestamp, + suggested_fee_recipient: config.attributes.suggested_fee_recipient(), + prev_randao: config.attributes.prev_randao(), + gas_limit: config + .attributes + .gas_limit + .unwrap_or(config.parent_header.gas_limit), + parent_beacon_block_root: config + .attributes + .payload_attributes + .parent_beacon_block_root, + extra_data: if chain_spec.is_holocene_active_at_timestamp(timestamp) { + config + .attributes + .get_holocene_extra_data(chain_spec.base_fee_params_at_timestamp(timestamp)) + .map_err(PayloadBuilderError::other)? + } else { + Default::default() + }, + }; + + let evm_env = self + .evm_config + .next_evm_env(&config.parent_header, &block_env_attributes) + .map_err(PayloadBuilderError::other)?; + + let ctx = OpPayloadBuilderCtx { + evm_config: self.evm_config.clone(), + da_config: self.config.da_config.clone(), + chain_spec, + config, + evm_env, + block_env_attributes, + cancel, + builder_signer: self.config.builder_signer, + metrics: self.metrics.clone(), + }; + + let builder = OpBuilder::new(best); + + let state_provider = self.client.state_by_block_hash(ctx.parent().hash())?; + let state = StateProviderDatabase::new(state_provider); + let metrics = ctx.metrics.clone(); + + if ctx.attributes().no_tx_pool { + let db = State::builder() + .with_database(state) + .with_bundle_update() + .build(); + builder.build(db, ctx) + } else { + // sequencer mode we can reuse cachedreads from previous runs + let db = State::builder() + .with_database(cached_reads.as_db_mut(state)) + .with_bundle_update() + .build(); + builder.build(db, ctx) + } + .map(|out| { + metrics + .total_block_built_duration + .record(block_build_start_time.elapsed()); + + out.with_cached_reads(cached_reads) + }) + } +} + +/// The type that builds the payload. +/// +/// Payload building for optimism is composed of several steps. +/// The first steps are mandatory and defined by the protocol. +/// +/// 1. first all System calls are applied. +/// 2. After canyon the forced deployed `create2deployer` must be loaded +/// 3. all sequencer transactions are executed (part of the payload attributes) +/// +/// Depending on whether the node acts as a sequencer and is allowed to include additional +/// transactions (`no_tx_pool == false`): +/// 4. include additional transactions +/// +/// And finally +/// 5. build the block: compute all roots (txs, state) +#[derive(derive_more::Debug)] +pub struct OpBuilder<'a, Txs> { + /// Yields the best transaction to include if transactions from the mempool are allowed. + best: Box Txs + 'a>, +} + +impl<'a, Txs> OpBuilder<'a, Txs> { + fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self { + Self { + best: Box::new(best), + } + } +} + +/// Holds the state after execution +#[derive(Debug)] +pub struct ExecutedPayload { + /// Tracked execution info + pub info: ExecutionInfo, +} + +impl OpBuilder<'_, Txs> { + /// Executes the payload and returns the outcome. + pub fn execute( + self, + state: &mut State, + ctx: &OpPayloadBuilderCtx, + ) -> Result, PayloadBuilderError> + where + DB: Database + AsRef

, + P: StorageRootProvider, + { + let Self { best } = self; + info!(target: "payload_builder", id=%ctx.payload_id(), parent_header = ?ctx.parent().hash(), parent_number = ctx.parent().number, "building new payload"); + + // 1. apply pre-execution changes + ctx.evm_config + .builder_for_next_block(state, ctx.parent(), ctx.block_env_attributes.clone()) + .map_err(PayloadBuilderError::other)? + .apply_pre_execution_changes()?; + + let sequencer_tx_start_time = Instant::now(); + + // 3. execute sequencer transactions + let mut info = ctx.execute_sequencer_transactions(state)?; + + ctx.metrics + .sequencer_tx_duration + .record(sequencer_tx_start_time.elapsed()); + + // 4. if mem pool transactions are requested we execute them + + // gas reserved for builder tx + let message = format!("Block Number: {}", ctx.block_number()) + .as_bytes() + .to_vec(); + let builder_tx_gas = ctx + .builder_signer() + .map_or(0, |_| estimate_gas_for_builder_tx(message.clone())); + let block_gas_limit = ctx.block_gas_limit() - builder_tx_gas; + // Save some space in the block_da_limit for builder tx + let builder_tx_da_size = ctx + .estimate_builder_tx_da_size(state, builder_tx_gas, message.clone()) + .unwrap_or(0); + let block_da_limit = ctx + .da_config + .max_da_block_size() + .map(|da_limit| { + let da_limit = da_limit.saturating_sub(builder_tx_da_size); + if da_limit == 0 { + error!("Builder tx da size subtraction caused max_da_block_size to be 0. No transaction would be included."); + } + da_limit + }); + + if !ctx.attributes().no_tx_pool { + let best_txs_start_time = Instant::now(); + let best_txs = best(ctx.best_transaction_attributes()); + ctx.metrics + .transaction_pool_fetch_duration + .record(best_txs_start_time.elapsed()); + if ctx + .execute_best_transactions( + &mut info, + state, + best_txs, + block_gas_limit, + block_da_limit, + )? + .is_some() + { + return Ok(BuildOutcomeKind::Cancelled); + } + } + + // Add builder tx to the block + ctx.add_builder_tx(&mut info, state, builder_tx_gas, message); + + let state_merge_start_time = Instant::now(); + + // merge all transitions into bundle state, this would apply the withdrawal balance changes + // and 4788 contract call + state.merge_transitions(BundleRetention::Reverts); + + ctx.metrics + .state_transition_merge_duration + .record(state_merge_start_time.elapsed()); + ctx.metrics + .payload_num_tx + .record(info.executed_transactions.len() as f64); + + let payload = ExecutedPayload { info }; + + ctx.metrics.block_built_success.increment(1); + Ok(BuildOutcomeKind::Better { payload }) + } + + /// Builds the payload on top of the state. + pub fn build( + self, + mut state: State, + ctx: OpPayloadBuilderCtx, + ) -> Result, PayloadBuilderError> + where + DB: Database + AsRef

, + P: StateRootProvider + HashedPostStateProvider + StorageRootProvider, + { + let ExecutedPayload { info } = match self.execute(&mut state, &ctx)? { + BuildOutcomeKind::Better { payload } | BuildOutcomeKind::Freeze(payload) => payload, + BuildOutcomeKind::Cancelled => return Ok(BuildOutcomeKind::Cancelled), + BuildOutcomeKind::Aborted { fees } => return Ok(BuildOutcomeKind::Aborted { fees }), + }; + + let block_number = ctx.block_number(); + let execution_outcome = ExecutionOutcome::new( + state.take_bundle(), + vec![info.receipts], + block_number, + Vec::new(), + ); + let receipts_root = execution_outcome + .generic_receipts_root_slow(block_number, |receipts| { + calculate_receipt_root_no_memo_optimism( + receipts, + &ctx.chain_spec, + ctx.attributes().timestamp(), + ) + }) + .expect("Number is in range"); + let logs_bloom = execution_outcome + .block_logs_bloom(block_number) + .expect("Number is in range"); + + // calculate the state root + let state_root_start_time = Instant::now(); + + let state_provider = state.database.as_ref(); + let hashed_state = state_provider.hashed_post_state(execution_outcome.state()); + let (state_root, trie_output) = { + state + .database + .as_ref() + .state_root_with_updates(hashed_state.clone()) + .inspect_err(|err| { + warn!(target: "payload_builder", + parent_header=%ctx.parent().hash(), + %err, + "failed to calculate state root for payload" + ); + })? + }; + + ctx.metrics + .state_root_calculation_duration + .record(state_root_start_time.elapsed()); + + let (withdrawals_root, requests_hash) = if ctx.is_isthmus_active() { + // withdrawals root field in block header is used for storage root of L2 predeploy + // `l2tol1-message-passer` + ( + Some( + isthmus::withdrawals_root(execution_outcome.state(), state.database.as_ref()) + .map_err(PayloadBuilderError::other)?, + ), + Some(EMPTY_REQUESTS_HASH), + ) + } else if ctx.is_canyon_active() { + (Some(EMPTY_WITHDRAWALS), None) + } else { + (None, None) + }; + + // create the block header + let transactions_root = proofs::calculate_transaction_root(&info.executed_transactions); + + // OP doesn't support blobs/EIP-4844. + // https://specs.optimism.io/protocol/exec-engine.html#ecotone-disable-blob-transactions + // Need [Some] or [None] based on hardfork to match block hash. + let (excess_blob_gas, blob_gas_used) = ctx.blob_fields(); + let extra_data = ctx.extra_data()?; + + let header = Header { + parent_hash: ctx.parent().hash(), + ommers_hash: EMPTY_OMMER_ROOT_HASH, + beneficiary: ctx.evm_env.block_env.beneficiary, + state_root, + transactions_root, + receipts_root, + withdrawals_root, + logs_bloom, + timestamp: ctx.attributes().payload_attributes.timestamp, + mix_hash: ctx.attributes().payload_attributes.prev_randao, + nonce: BEACON_NONCE.into(), + base_fee_per_gas: Some(ctx.base_fee()), + number: ctx.parent().number + 1, + gas_limit: ctx.block_gas_limit(), + difficulty: U256::ZERO, + gas_used: info.cumulative_gas_used, + extra_data, + parent_beacon_block_root: ctx.attributes().payload_attributes.parent_beacon_block_root, + blob_gas_used, + excess_blob_gas, + requests_hash, + }; + + // seal the block + let block = alloy_consensus::Block::::new( + header, + BlockBody { + transactions: info.executed_transactions, + ommers: vec![], + withdrawals: ctx.withdrawals().cloned(), + }, + ); + + let sealed_block = Arc::new(block.seal_slow()); + info!(target: "payload_builder", id=%ctx.attributes().payload_id(), "sealed built block"); + + // create the executed block data + let executed: ExecutedBlockWithTrieUpdates = ExecutedBlockWithTrieUpdates { + block: ExecutedBlock { + recovered_block: Arc::new(RecoveredBlock::< + alloy_consensus::Block, + >::new_sealed( + sealed_block.as_ref().clone(), info.executed_senders + )), + execution_output: Arc::new(execution_outcome), + hashed_state: Arc::new(hashed_state), + }, + trie: ExecutedTrieUpdates::Present(Arc::new(trie_output)), + }; + + let no_tx_pool = ctx.attributes().no_tx_pool; + + let payload = OpBuiltPayload::new( + ctx.payload_id(), + sealed_block, + info.total_fees, + Some(executed), + ); + + ctx.metrics + .payload_byte_size + .record(payload.block().size() as f64); + + if no_tx_pool { + // if `no_tx_pool` is set only transactions from the payload attributes will be included + // in the payload. In other words, the payload is deterministic and we can + // freeze it once we've successfully built it. + Ok(BuildOutcomeKind::Freeze(payload)) + } else { + Ok(BuildOutcomeKind::Better { payload }) + } + } +} From 6ca8eb7e1d2fcf34a6182b8ccd223527df0bcf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Wed, 25 Jun 2025 13:10:36 +0200 Subject: [PATCH 2/8] PoC obtaining TXs from auction running on pod --- Cargo.lock | 244 +++++++++++++++--- crates/op-rbuilder/Cargo.toml | 44 ++-- crates/op-rbuilder/src/args/mod.rs | 3 + crates/op-rbuilder/src/args/op.rs | 23 ++ crates/op-rbuilder/src/builders/mod.rs | 6 + crates/op-rbuilder/src/builders/pod/config.rs | 20 ++ crates/op-rbuilder/src/builders/pod/mod.rs | 21 +- .../op-rbuilder/src/builders/pod/payload.rs | 176 ++++++------- .../src/builders/pod/pod_client.rs | 95 +++++++ crates/op-rbuilder/src/launcher.rs | 9 +- 10 files changed, 478 insertions(+), 163 deletions(-) create mode 100644 crates/op-rbuilder/src/builders/pod/config.rs create mode 100644 crates/op-rbuilder/src/builders/pod/pod_client.rs diff --git a/Cargo.lock b/Cargo.lock index 9969f843..67144b4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "generic-array", ] @@ -461,7 +461,7 @@ dependencies = [ "ruint", "rustc-hash 2.1.1", "serde", - "sha3", + "sha3 0.10.8", "tiny-keccak", ] @@ -492,7 +492,7 @@ dependencies = [ "ruint", "rustc-hash 2.1.1", "serde", - "sha3", + "sha3 0.10.8", "tiny-keccak", ] @@ -1903,6 +1903,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a229bfd78e4827c91b9b95784f69492c1b77c1ab75a45a8a037b139215086f94" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block-padding" version = "0.3.3" @@ -2365,7 +2374,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", ] @@ -2397,9 +2406,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -2407,9 +2416,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -2419,9 +2428,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -2565,6 +2574,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" + [[package]] name = "const_format" version = "0.2.34" @@ -2762,6 +2777,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a23fa214dea9efd4dacee5a5614646b30216ae0f05d4bb51bafb50e9da1c5be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctor" version = "0.4.2" @@ -2914,7 +2938,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "sha3", + "sha3 0.10.8", "time", "x509-parser", ] @@ -2942,7 +2966,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", "pem-rfc7468", "zeroize", ] @@ -3079,11 +3103,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", - "crypto-common", + "const-oid 0.9.6", + "crypto-common 0.1.6", "subtle", ] +[[package]] +name = "digest" +version = "0.11.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460dd7f37e4950526b54a5a6b1f41b6c8e763c58eb9a8fc8fc05ba5c2f44ca7b" +dependencies = [ + "block-buffer 0.11.0-rc.4", + "const-oid 0.10.1", + "crypto-common 0.2.0-rc.3", +] + [[package]] name = "dirs" version = "5.0.1" @@ -3340,7 +3375,7 @@ dependencies = [ "rand 0.8.5", "secp256k1", "serde", - "sha3", + "sha3 0.10.8", "zeroize", ] @@ -4181,6 +4216,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hybrid-array" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d15931895091dea5c47afa5b3c9a01ba634b311919fd4d41388fa0e3d76af" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.6.0" @@ -5154,6 +5198,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak" +version = "0.2.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cdd4f0dc5807b9a2b25dd48a3f58e862606fe7bd47f41ecde36e97422d7e90" +dependencies = [ + "cpufeatures", +] + [[package]] name = "keccak-asm" version = "0.1.4" @@ -6031,6 +6084,20 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "op-alloy" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7f8b661d4d0b3e767d608c3763296c0c23bdf59cd5c21fc4f9922648e30ce6" +dependencies = [ + "op-alloy-consensus", + "op-alloy-network", + "op-alloy-provider", + "op-alloy-rpc-jsonrpsee", + "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", +] + [[package]] name = "op-alloy-consensus" version = "0.17.2" @@ -6071,6 +6138,21 @@ dependencies = [ "op-alloy-rpc-types", ] +[[package]] +name = "op-alloy-provider" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57210fbc4e437b8f8e32b197e43f4a4d66f0914db8bf74acc6c444f14050aaea" +dependencies = [ + "alloy-network", + "alloy-primitives 1.2.0", + "alloy-provider", + "alloy-rpc-types-engine", + "alloy-transport", + "async-trait", + "op-alloy-rpc-types-engine", +] + [[package]] name = "op-alloy-rpc-jsonrpsee" version = "0.17.2" @@ -6132,6 +6214,7 @@ dependencies = [ "alloy-op-evm", "alloy-primitives 1.2.0", "alloy-provider", + "alloy-rlp", "alloy-rpc-client", "alloy-rpc-types-beacon", "alloy-rpc-types-engine", @@ -6143,7 +6226,7 @@ dependencies = [ "async-trait", "bollard", "chrono", - "clap 4.5.39", + "clap 4.5.40", "clap_builder", "ctor", "dashmap 6.1.0", @@ -6154,6 +6237,7 @@ dependencies = [ "futures-util", "hex", "http", + "itertools 0.14.0", "jsonrpsee 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpsee-core 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpsee-types 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6168,7 +6252,9 @@ dependencies = [ "op-alloy-rpc-types-engine", "op-revm", "opentelemetry 0.29.1", + "optimism-tx-auction", "parking_lot", + "pod-sdk", "rand 0.9.1", "reth", "reth-basic-payload-builder", @@ -6224,7 +6310,7 @@ dependencies = [ "serde_json", "serde_with", "serde_yaml", - "sha3", + "sha3 0.10.8", "shellexpand", "tar", "tdx", @@ -6475,6 +6561,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "optimism-tx-auction" +version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +dependencies = [ + "alloy", + "anyhow", + "clap 4.5.40", + "op-alloy", + "pod-sdk", + "pod-types", + "tokio", + "tracing", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -6770,6 +6871,56 @@ dependencies = [ "crunchy", ] +[[package]] +name = "pod-sdk" +version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-primitives 1.2.0", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-types", + "alloy-signer", + "alloy-signer-local", + "alloy-sol-types 1.2.0", + "alloy-transport", + "alloy-transport-http", + "anyhow", + "async-trait", + "futures", + "hex", + "pod-types", + "serde", +] + +[[package]] +name = "pod-types" +version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +dependencies = [ + "alloy-consensus", + "alloy-primitives 1.2.0", + "alloy-rpc-types", + "alloy-signer", + "alloy-signer-local", + "alloy-sol-types 1.2.0", + "anyhow", + "async-trait", + "base64 0.22.1", + "bytes", + "hex", + "itertools 0.13.0", + "k256", + "serde", + "sha3 0.11.0-rc.0", + "tokio", + "utoipa", +] + [[package]] name = "pollster" version = "0.4.0" @@ -7397,7 +7548,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.4.8#127595e23079de2c494 dependencies = [ "alloy-rpc-types", "aquamarine", - "clap 4.5.39", + "clap 4.5.40", "eyre", "reth-chainspec", "reth-cli-runner", @@ -7517,7 +7668,7 @@ version = "1.4.8" source = "git+https://github.com/paradigmxyz/reth?tag=v1.4.8#127595e23079de2c494048d0821ea1f1107eb624" dependencies = [ "alloy-genesis", - "clap 4.5.39", + "clap 4.5.40", "eyre", "reth-cli-runner", "reth-db", @@ -7537,7 +7688,7 @@ dependencies = [ "alloy-primitives 1.2.0", "alloy-rlp", "backon", - "clap 4.5.39", + "clap 4.5.40", "comfy-table", "crossterm", "eyre", @@ -7947,7 +8098,7 @@ dependencies = [ "reth-network-peers", "secp256k1", "sha2 0.10.9", - "sha3", + "sha3 0.10.8", "thiserror 2.0.12", "tokio", "tokio-stream", @@ -8235,7 +8386,7 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types", "backon", - "clap 4.5.39", + "clap 4.5.40", "eyre", "futures", "reth-basic-payload-builder", @@ -8872,7 +9023,7 @@ dependencies = [ "alloy-eips", "alloy-primitives 1.2.0", "alloy-rpc-types-engine", - "clap 4.5.39", + "clap 4.5.40", "derive_more", "dirs-next", "eyre", @@ -9043,7 +9194,7 @@ dependencies = [ "alloy-eips", "alloy-primitives 1.2.0", "alloy-rlp", - "clap 4.5.39", + "clap 4.5.40", "derive_more", "eyre", "futures-util", @@ -9151,7 +9302,7 @@ dependencies = [ "alloy-primitives 1.2.0", "alloy-rpc-types-engine", "alloy-rpc-types-eth", - "clap 4.5.39", + "clap 4.5.40", "eyre", "op-alloy-consensus", "op-alloy-network", @@ -10017,7 +10168,7 @@ version = "1.4.8" source = "git+https://github.com/paradigmxyz/reth?tag=v1.4.8#127595e23079de2c494048d0821ea1f1107eb624" dependencies = [ "alloy-primitives 1.2.0", - "clap 4.5.39", + "clap 4.5.40", "derive_more", "serde", "strum 0.27.1", @@ -10112,7 +10263,7 @@ name = "reth-tracing" version = "1.4.8" source = "git+https://github.com/paradigmxyz/reth?tag=v1.4.8#127595e23079de2c494048d0821ea1f1107eb624" dependencies = [ - "clap 4.5.39", + "clap 4.5.40", "eyre", "rolling-file", "tracing", @@ -10603,7 +10754,7 @@ dependencies = [ "alloy-rpc-types-engine", "alloy-rpc-types-eth", "alloy-serde", - "clap 4.5.39", + "clap 4.5.40", "dotenvy", "eyre", "futures", @@ -11224,7 +11375,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ "digest 0.10.7", - "keccak", + "keccak 0.1.5", +] + +[[package]] +name = "sha3" +version = "0.11.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e6a92fd180fd205defdc0b78288ce847c7309d329fd6647a814567e67db50e" +dependencies = [ + "digest 0.11.0-rc.0", + "keccak 0.2.0-pre.0", ] [[package]] @@ -12485,7 +12646,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "subtle", ] @@ -12571,6 +12732,29 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "utoipa" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" +dependencies = [ + "indexmap 2.9.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "uuid" version = "1.17.0" diff --git a/crates/op-rbuilder/Cargo.toml b/crates/op-rbuilder/Cargo.toml index 1076478e..5b6fbd23 100644 --- a/crates/op-rbuilder/Cargo.toml +++ b/crates/op-rbuilder/Cargo.toml @@ -69,6 +69,7 @@ alloy-network.workspace = true alloy-provider.workspace = true alloy-serde.workspace = true alloy-json-rpc.workspace = true +alloy-rlp.workspace = true # op alloy-op-evm.workspace = true @@ -132,6 +133,9 @@ tar = { version = "0.4", optional = true } ctor = { version = "0.4.2", optional = true } rlimit = { version = "0.10", optional = true } macros = { path = "src/tests/framework/macros", optional = true } +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "05b3f123d165de2b60c70621f40c7c3a6b1a9b07" } +pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "05b3f123d165de2b60c70621f40c7c3a6b1a9b07" } +itertools = "0.14.0" [target.'cfg(unix)'.dependencies] tikv-jemallocator = { version = "0.6", optional = true } @@ -142,7 +146,7 @@ vergen-git2.workspace = true [dev-dependencies] alloy-provider = { workspace = true, default-features = true, features = [ - "txpool-api", + "txpool-api", ] } tempfile = "3.8" macros = { path = "src/tests/framework/macros" } @@ -158,15 +162,15 @@ rlimit = { version = "0.10" } default = ["jemalloc"] jemalloc = [ - "dep:tikv-jemallocator", - "reth-cli-util/jemalloc", - "reth-optimism-cli/jemalloc", + "dep:tikv-jemallocator", + "reth-cli-util/jemalloc", + "reth-optimism-cli/jemalloc", ] jemalloc-prof = [ - "jemalloc", - "tikv-jemallocator?/profiling", - "reth/jemalloc-prof", - "reth-cli-util/jemalloc-prof", + "jemalloc", + "tikv-jemallocator?/profiling", + "reth/jemalloc-prof", + "reth-cli-util/jemalloc-prof", ] min-error-logs = ["tracing/release_max_level_error"] @@ -176,14 +180,14 @@ min-debug-logs = ["tracing/release_max_level_debug"] min-trace-logs = ["tracing/release_max_level_trace"] testing = [ - "dashmap", - "nanoid", - "reth-ipc", - "reth-node-builder/test-utils", - "bollard", - "ctor", - "macros", - "rlimit", + "dashmap", + "nanoid", + "reth-ipc", + "reth-node-builder/test-utils", + "bollard", + "ctor", + "macros", + "rlimit", ] interop = [] @@ -202,10 +206,10 @@ ci-features = [ "min-info-logs", "min-debug-logs", "min-trace-logs", - "testing", - "interop", - "telemetry", - "custom-engine-api", + "testing", + "interop", + "telemetry", + "custom-engine-api", ] [[bin]] diff --git a/crates/op-rbuilder/src/args/mod.rs b/crates/op-rbuilder/src/args/mod.rs index 0c0b1a4e..16e53962 100644 --- a/crates/op-rbuilder/src/args/mod.rs +++ b/crates/op-rbuilder/src/args/mod.rs @@ -75,6 +75,9 @@ impl CliExt for Cli { if node_command.ext.flashblocks.enabled { return BuilderMode::Flashblocks; } + if node_command.ext.pod.is_enabled { + return BuilderMode::Pod; + } } BuilderMode::Standard } diff --git a/crates/op-rbuilder/src/args/op.rs b/crates/op-rbuilder/src/args/op.rs index 784aeb7c..9d307761 100644 --- a/crates/op-rbuilder/src/args/op.rs +++ b/crates/op-rbuilder/src/args/op.rs @@ -5,6 +5,7 @@ //! clap [Args](clap::Args) for optimism rollup configuration use crate::{flashtestations::args::FlashtestationsArgs, tx_signer::Signer}; +use alloy_primitives::Address; use anyhow::{anyhow, Result}; use clap::Parser; use reth_optimism_cli::commands::Commands; @@ -51,6 +52,8 @@ pub struct OpRbuilderArgs { )] pub playground: Option, #[command(flatten)] + pub pod: PodArgs, + #[command(flatten)] pub flashblocks: FlashblocksArgs, #[command(flatten)] pub telemetry: TelemetryArgs, @@ -149,6 +152,26 @@ impl Default for FlashblocksArgs { } } +#[derive(Debug, Clone, PartialEq, Eq, clap::Args)] +pub struct PodArgs { + #[arg(long = "pod.enabled", default_value = "false", env = "ENABLE_POD")] + pub is_enabled: bool, + + #[arg( + long = "pod.rpc-url", + env = "POD_RPC_URL", + default_value = "ws://127.0.0.1:8545" + )] + pub pod_rpc_url: String, + + #[arg( + long = "pod.contract-address", + env = "POD_CONTRACT_ADDRESS", + default_value = "0x12296f2D128530a834460DF6c36a2895B793F26d" + )] + pub pod_contract_address: Address, +} + /// Parameters for telemetry configuration #[derive(Debug, Clone, Default, PartialEq, Eq, clap::Args)] pub struct TelemetryArgs { diff --git a/crates/op-rbuilder/src/builders/mod.rs b/crates/op-rbuilder/src/builders/mod.rs index 1c41f370..9c74f404 100644 --- a/crates/op-rbuilder/src/builders/mod.rs +++ b/crates/op-rbuilder/src/builders/mod.rs @@ -18,10 +18,12 @@ mod builder_tx; mod context; mod flashblocks; mod generator; +mod pod; mod standard; pub use builder_tx::BuilderTx; pub use flashblocks::FlashblocksBuilder; +pub use pod::PodBuilder; pub use standard::StandardBuilder; /// Defines the payload building mode for the OP builder. @@ -34,6 +36,10 @@ pub enum BuilderMode { /// block every short interval and makes it available through a websocket update /// then merges them into a full block every chain block time. Flashblocks, + /// Uses the pod payload builder that builds blocks every chain block time + /// but picks transactions from an auction running on pod, selecting the highest + /// bidding transactions. + Pod, } /// Defines the interface for any block builder implementation API entry point. diff --git a/crates/op-rbuilder/src/builders/pod/config.rs b/crates/op-rbuilder/src/builders/pod/config.rs new file mode 100644 index 00000000..90fe7d24 --- /dev/null +++ b/crates/op-rbuilder/src/builders/pod/config.rs @@ -0,0 +1,20 @@ +use crate::args::OpRbuilderArgs; +use alloy_primitives::Address; + +/// Configuration values that are specific to the flashblocks builder. +#[derive(Debug, Clone)] +pub struct Config { + pub rpc_url: String, + pub contract_address: Address, +} + +impl TryFrom for Config { + type Error = eyre::Report; + + fn try_from(args: OpRbuilderArgs) -> Result { + Ok(Self { + rpc_url: args.pod.pod_rpc_url, + contract_address: args.pod.pod_contract_address, + }) + } +} diff --git a/crates/op-rbuilder/src/builders/pod/mod.rs b/crates/op-rbuilder/src/builders/pod/mod.rs index 98e9b44f..f43dd548 100644 --- a/crates/op-rbuilder/src/builders/pod/mod.rs +++ b/crates/op-rbuilder/src/builders/pod/mod.rs @@ -1,21 +1,24 @@ -use payload::StandardPayloadBuilderBuilder; +use config::Config; +use payload::PodPayloadBuilderBuilder; use reth_node_builder::components::BasicPayloadServiceBuilder; use crate::traits::{NodeBounds, PoolBounds}; use super::BuilderConfig; +mod config; mod payload; +mod pod_client; -/// Block building strategy that builds blocks using the standard approach by +/// Block building strategy that builds blocks using auction running on pod by /// producing blocks every chain block time. -pub struct StandardBuilder; +pub struct PodBuilder; -impl super::PayloadBuilder for StandardBuilder { - type Config = (); +impl super::PayloadBuilder for PodBuilder { + type Config = Config; type ServiceBuilder - = BasicPayloadServiceBuilder + = BasicPayloadServiceBuilder where Node: NodeBounds, Pool: PoolBounds; @@ -27,8 +30,8 @@ impl super::PayloadBuilder for StandardBuilder { Node: NodeBounds, Pool: PoolBounds, { - Ok(BasicPayloadServiceBuilder::new( - StandardPayloadBuilderBuilder(config), - )) + Ok(BasicPayloadServiceBuilder::new(PodPayloadBuilderBuilder( + config, + ))) } } diff --git a/crates/op-rbuilder/src/builders/pod/payload.rs b/crates/op-rbuilder/src/builders/pod/payload.rs index eaf98c2c..7c65f17b 100644 --- a/crates/op-rbuilder/src/builders/pod/payload.rs +++ b/crates/op-rbuilder/src/builders/pod/payload.rs @@ -1,9 +1,9 @@ use crate::{ builders::{generator::BuildArguments, BuilderConfig}, - flashtestations::service::spawn_flashtestations_service, metrics::OpRBuilderMetrics, primitives::reth::ExecutionInfo, traits::{ClientBounds, NodeBounds, PayloadTxsBounds, PoolBounds}, + tx::FBPooledTransaction, }; use alloy_consensus::{ constants::EMPTY_WITHDRAWALS, proofs, BlockBody, Header, EMPTY_OMMER_ROOT_HASH, @@ -21,7 +21,7 @@ use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes}; use reth_optimism_forks::OpHardforks; use reth_optimism_node::{OpBuiltPayload, OpPayloadBuilderAttributes}; use reth_optimism_primitives::{OpPrimitives, OpTransactionSigned}; -use reth_payload_util::{BestPayloadTransactions, NoopPayloadTransactions, PayloadTransactions}; +use reth_payload_util::NoopPayloadTransactions; use reth_primitives::RecoveredBlock; use reth_provider::{ ExecutionOutcome, HashedPostStateProvider, ProviderError, StateRootProvider, @@ -30,130 +30,87 @@ use reth_provider::{ use reth_revm::{ database::StateProviderDatabase, db::states::bundle_state::BundleRetention, State, }; -use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool}; +use reth_tasks::TaskExecutor; +use reth_transaction_pool::BestTransactionsAttributes; use revm::Database; use std::{sync::Arc, time::Instant}; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; -use super::super::context::{estimate_gas_for_builder_tx, OpPayloadBuilderCtx}; +use super::{ + super::context::{estimate_gas_for_builder_tx, OpPayloadBuilderCtx}, + config::Config, + pod_client::PodClient, +}; -pub struct StandardPayloadBuilderBuilder(pub BuilderConfig<()>); +pub struct PodPayloadBuilderBuilder(pub BuilderConfig); -impl PayloadBuilderBuilder for StandardPayloadBuilderBuilder +impl PayloadBuilderBuilder for PodPayloadBuilderBuilder where Node: NodeBounds, Pool: PoolBounds, { - type PayloadBuilder = StandardOpPayloadBuilder; + type PayloadBuilder = PodOpPayloadBuilder; async fn build_payload_builder( self, ctx: &BuilderContext, - pool: Pool, + _: Pool, _evm_config: OpEvmConfig, ) -> eyre::Result { - let signer = self.0.builder_signer; - - if self.0.flashtestations_config.flashtestations_enabled { - let funding_signer = signer.expect("Key to fund TEE generated address not set"); - match spawn_flashtestations_service( - self.0.flashtestations_config.clone(), - funding_signer, - ctx, - ) - .await - { - Ok(service) => service, - Err(e) => { - tracing::warn!(error = %e, "Failed to spawn flashtestations service, falling back to standard builder tx"); - return Ok(StandardOpPayloadBuilder::new( - OpEvmConfig::optimism(ctx.chain_spec()), - pool, - ctx.provider().clone(), - self.0.clone(), - )); - } - }; - - if self.0.flashtestations_config.enable_block_proofs { - // TODO: flashtestations end of block transaction - } - } - - Ok(StandardOpPayloadBuilder::new( + PodOpPayloadBuilder::new( OpEvmConfig::optimism(ctx.chain_spec()), - pool, + ctx.task_executor().clone(), ctx.provider().clone(), self.0.clone(), - )) + ) + .await } } /// Optimism's payload builder #[derive(Debug, Clone)] -pub struct StandardOpPayloadBuilder { +pub struct PodOpPayloadBuilder { /// The type responsible for creating the evm. pub evm_config: OpEvmConfig, - /// The transaction pool - pub pool: Pool, /// Node client pub client: Client, + pod_client: Arc, + executor: TaskExecutor, /// Settings for the builder, e.g. DA settings. - pub config: BuilderConfig<()>, - /// The type responsible for yielding the best transactions for the payload if mempool - /// transactions are allowed. - pub best_transactions: Txs, + pub config: BuilderConfig, /// The metrics for the builder pub metrics: Arc, } -impl StandardOpPayloadBuilder { - /// `OpPayloadBuilder` constructor. - pub fn new( +impl PodOpPayloadBuilder { + pub async fn new( evm_config: OpEvmConfig, - pool: Pool, + executor: TaskExecutor, client: Client, - config: BuilderConfig<()>, - ) -> Self { - Self { - pool, + config: BuilderConfig, + ) -> eyre::Result { + info!(target: "payload_builder", contract_address = %config.specific.contract_address, rpc_url = config.specific.rpc_url, "Initializing PodOpPayloadBuilder"); + Ok(Self { client, + executor, + pod_client: Arc::new( + PodClient::new( + config.specific.rpc_url.clone(), + config.specific.contract_address, + ) + .await?, + ), config, evm_config, - best_transactions: (), metrics: Default::default(), - } - } -} - -/// A type that returns a the [`PayloadTransactions`] that should be included in the pool. -pub trait OpPayloadTransactions: Clone + Send + Sync + Unpin + 'static { - /// Returns an iterator that yields the transaction in the order they should get included in the - /// new payload. - fn best_transactions>( - &self, - pool: Pool, - attr: BestTransactionsAttributes, - ) -> impl PayloadTransactions; -} - -impl OpPayloadTransactions for () { - fn best_transactions>( - &self, - pool: Pool, - attr: BestTransactionsAttributes, - ) -> impl PayloadTransactions { - BestPayloadTransactions::new(pool.best_transactions_with_attributes(attr)) + }) } } -impl reth_basic_payload_builder::PayloadBuilder - for StandardOpPayloadBuilder +impl reth_basic_payload_builder::PayloadBuilder for PodOpPayloadBuilder where - Pool: PoolBounds, Client: ClientBounds, - Txs: OpPayloadTransactions, { type Attributes = OpPayloadBuilderAttributes; type BuiltPayload = OpBuiltPayload; @@ -162,8 +119,6 @@ where &self, args: reth_basic_payload_builder::BuildArguments, ) -> Result, PayloadBuilderError> { - let pool = self.pool.clone(); - let reth_basic_payload_builder::BuildArguments { cached_reads, config, @@ -177,10 +132,18 @@ where cancel: CancellationToken::new(), }; - self.build_payload(args, |attrs| { - #[allow(clippy::unit_arg)] - self.best_transactions - .best_transactions(pool.clone(), attrs) + self.build_payload(args, |timestamp, attrs| { + let pod_client = self.pod_client.clone(); + let handle = self.executor.handle().clone(); + let txs = std::thread::spawn(move || { + handle.block_on(pod_client.best_transactions(timestamp, attrs)) + }) + .join() + .unwrap() + .unwrap(); + + info!(target: "payload_builder", len=txs.len(), "fetched best transactions"); + txs }) } @@ -203,17 +166,16 @@ where cached_reads: Default::default(), cancel: Default::default(), }; - self.build_payload(args, |_| { - NoopPayloadTransactions::::default() + self.build_payload(args, |_, _| { + NoopPayloadTransactions::::default() })? .into_payload() .ok_or_else(|| PayloadBuilderError::MissingPayload) } } -impl StandardOpPayloadBuilder +impl PodOpPayloadBuilder where - Pool: PoolBounds, Client: ClientBounds, { /// Constructs an Optimism payload from the transactions sent via the @@ -224,11 +186,15 @@ where /// Given build arguments including an Optimism client, transaction pool, /// and configuration, this function creates a transaction payload. Returns /// a result indicating success with the payload or an error in case of failure. - fn build_payload<'a, Txs: PayloadTxsBounds>( + fn build_payload<'a, Txs, F>( &self, args: BuildArguments, OpBuiltPayload>, - best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a, - ) -> Result, PayloadBuilderError> { + best: F, + ) -> Result, PayloadBuilderError> + where + Txs: PayloadTxsBounds, + F: FnOnce(u64, BestTransactionsAttributes) -> Txs + Send + Sync + 'a, + { let block_build_start_time = Instant::now(); let BuildArguments { @@ -324,16 +290,17 @@ where /// And finally /// 5. build the block: compute all roots (txs, state) #[derive(derive_more::Debug)] -pub struct OpBuilder<'a, Txs> { +pub struct OpBuilder Txs> { /// Yields the best transaction to include if transactions from the mempool are allowed. - best: Box Txs + 'a>, + best: F, } -impl<'a, Txs> OpBuilder<'a, Txs> { - fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self { - Self { - best: Box::new(best), - } +impl OpBuilder +where + F: FnOnce(u64, BestTransactionsAttributes) -> Txs + Send + Sync, +{ + fn new(best: F) -> Self { + Self { best } } } @@ -344,7 +311,7 @@ pub struct ExecutedPayload { pub info: ExecutionInfo, } -impl OpBuilder<'_, Txs> { +impl Txs> OpBuilder { /// Executes the payload and returns the outcome. pub fn execute( self, @@ -400,7 +367,10 @@ impl OpBuilder<'_, Txs> { if !ctx.attributes().no_tx_pool { let best_txs_start_time = Instant::now(); - let best_txs = best(ctx.best_transaction_attributes()); + let best_txs = best( + ctx.attributes().timestamp(), + ctx.best_transaction_attributes(), + ); ctx.metrics .transaction_pool_fetch_duration .record(best_txs_start_time.elapsed()); diff --git a/crates/op-rbuilder/src/builders/pod/pod_client.rs b/crates/op-rbuilder/src/builders/pod/pod_client.rs new file mode 100644 index 00000000..44b8cbdf --- /dev/null +++ b/crates/op-rbuilder/src/builders/pod/pod_client.rs @@ -0,0 +1,95 @@ +use std::{collections::VecDeque, fmt::Debug}; + +use alloy_primitives::Address; +use alloy_rlp::Decodable; +use itertools::Itertools; +use pod_auction::client::AuctionClient; +use reth_optimism_primitives::OpTransactionSigned; +use reth_optimism_txpool::OpPooledTransaction; +use reth_payload_util::PayloadTransactions; +use reth_primitives::Recovered; +use reth_transaction_pool::BestTransactionsAttributes; + +use crate::tx::FBPooledTransaction; + +pub(super) struct PodClient { + client: AuctionClient, + rpc_url: String, +} + +#[derive(Debug)] +pub(super) struct Transactions(VecDeque); + +impl PodClient { + pub async fn new(rpc_url: String, contract_address: Address) -> eyre::Result { + let client = AuctionClient::new(rpc_url.clone(), contract_address).await; + + Ok(Self { client, rpc_url }) + } + + pub async fn best_transactions( + &self, + timestamp_secs: u64, + _attrs: BestTransactionsAttributes, + ) -> eyre::Result { + let timestamp = timestamp_secs - 2; + tracing::trace!(target: "payload_builder", timestamp, "querying best transactions"); + let bids = self.client.bids(timestamp).await.unwrap_or_else(|err| { + tracing::error!(target: "payload_builder", ?err, "failed to fetch bids from pod"); + Vec::new() + }); + let transactions = bids + .into_iter() + .sorted_by_key(|bid| { + // Sort by the bid amount in descending order + bid.amount + }) + .map(|bid| { + let signed_recovered = + Recovered::::decode(&mut bid.data.as_slice()).unwrap(); + let pooled_tx = OpPooledTransaction::new(signed_recovered, bid.data.len()); + tracing::info!(target: "payload_builder", tx=%pooled_tx.transaction.tx_hash(), bid=%bid.amount, "fetched tx from pod: {:?}", pooled_tx); + + pooled_tx.into() + }) + .collect::>(); + Ok(Transactions(transactions)) + } +} + +impl Debug for PodClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PodClient") + .field("rpc_url", &self.rpc_url) + .finish() + } +} + +impl PayloadTransactions for Transactions { + type Transaction = FBPooledTransaction; + /// Returns the next transaction to include in the block. + fn next( + &mut self, + // In the future, `ctx` can include access to state for block building purposes. + _ctx: (), + ) -> Option { + self.0.pop_front() + } + + /// Exclude descendants of the transaction with given sender and nonce from the iterator, + /// because this transaction won't be included in the block. + fn mark_invalid(&mut self, sender: Address, nonce: u64) { + tracing::warn!( + target: "payload_builder", + %sender, + nonce, + "mark_invalid called" + ); + } +} + +impl Transactions { + pub fn len(&self) -> usize { + self.0.len() + } +} diff --git a/crates/op-rbuilder/src/launcher.rs b/crates/op-rbuilder/src/launcher.rs index 29f5bd7c..d8d05ec9 100644 --- a/crates/op-rbuilder/src/launcher.rs +++ b/crates/op-rbuilder/src/launcher.rs @@ -2,7 +2,9 @@ use eyre::Result; use crate::{ args::*, - builders::{BuilderConfig, BuilderMode, FlashblocksBuilder, PayloadBuilder, StandardBuilder}, + builders::{ + BuilderConfig, BuilderMode, FlashblocksBuilder, PayloadBuilder, PodBuilder, StandardBuilder, + }, metrics::VERSION, monitor_tx_pool::monitor_tx_pool, primitives::reth::engine_api_builder::OpEngineApiBuilder, @@ -56,6 +58,11 @@ pub fn launch() -> Result<()> { let launcher = BuilderLauncher::::new(); cli_app.run(launcher)?; } + BuilderMode::Pod => { + tracing::info!("Starting OP builder in pod mode"); + let launcher = BuilderLauncher::::new(); + cli_app.run(launcher)?; + } } Ok(()) } From 5c37cd8a6b53f54d925ead1025079a8480c902ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 26 Jun 2025 15:30:06 +0200 Subject: [PATCH 3/8] Fix TX ordering and add logs --- .../op-rbuilder/src/builders/pod/payload.rs | 3 ++- .../src/builders/pod/pod_client.rs | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/op-rbuilder/src/builders/pod/payload.rs b/crates/op-rbuilder/src/builders/pod/payload.rs index 7c65f17b..e7778ef7 100644 --- a/crates/op-rbuilder/src/builders/pod/payload.rs +++ b/crates/op-rbuilder/src/builders/pod/payload.rs @@ -126,6 +126,7 @@ where best_payload: _, } = args; + let block_number = config.parent_header.header().number + 1; let args = BuildArguments { cached_reads, config, @@ -142,7 +143,7 @@ where .unwrap() .unwrap(); - info!(target: "payload_builder", len=txs.len(), "fetched best transactions"); + info!(target: "payload_builder", block=block_number, len=txs.len(), "fetched best transactions"); txs }) } diff --git a/crates/op-rbuilder/src/builders/pod/pod_client.rs b/crates/op-rbuilder/src/builders/pod/pod_client.rs index 44b8cbdf..3dfb5c31 100644 --- a/crates/op-rbuilder/src/builders/pod/pod_client.rs +++ b/crates/op-rbuilder/src/builders/pod/pod_client.rs @@ -42,15 +42,22 @@ impl PodClient { .into_iter() .sorted_by_key(|bid| { // Sort by the bid amount in descending order - bid.amount + -bid.amount }) - .map(|bid| { - let signed_recovered = - Recovered::::decode(&mut bid.data.as_slice()).unwrap(); - let pooled_tx = OpPooledTransaction::new(signed_recovered, bid.data.len()); - tracing::info!(target: "payload_builder", tx=%pooled_tx.transaction.tx_hash(), bid=%bid.amount, "fetched tx from pod: {:?}", pooled_tx); + .filter_map(|bid| { + let recovered = match + Recovered::::decode(&mut bid.data.as_slice()) { + Ok(tx) => { + tracing::info!(target: "payload_builder", tx=%tx.tx_hash(), bid=%bid.amount, "fetched tx from pod: {tx:?}"); + Some(tx) + }, + Err(error) => { + tracing::warn!(target: "payload_builder", ?error, "failed to decode transaction from pod"); + None + } + }?; - pooled_tx.into() + Some(OpPooledTransaction::new(recovered, bid.data.len()).into()) }) .collect::>(); Ok(Transactions(transactions)) From 4f9ba1a8af101d86523a6a71f8fc81f9b820e297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Tue, 15 Jul 2025 13:57:53 +0200 Subject: [PATCH 4/8] [wip] require bid = max_priority_fee --- Cargo.lock | 8 +++--- crates/op-rbuilder/Cargo.toml | 4 +-- .../op-rbuilder/src/builders/pod/payload.rs | 7 ++++- .../src/builders/pod/pod_client.rs | 27 ++++++++++++------- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67144b4b..30369a96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6564,14 +6564,16 @@ dependencies = [ [[package]] name = "optimism-tx-auction" version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" dependencies = [ "alloy", "anyhow", "clap 4.5.40", + "humantime", "op-alloy", "pod-sdk", "pod-types", + "rand 0.9.1", "tokio", "tracing", ] @@ -6874,7 +6876,7 @@ dependencies = [ [[package]] name = "pod-sdk" version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6900,7 +6902,7 @@ dependencies = [ [[package]] name = "pod-types" version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=05b3f123d165de2b60c70621f40c7c3a6b1a9b07#05b3f123d165de2b60c70621f40c7c3a6b1a9b07" +source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" dependencies = [ "alloy-consensus", "alloy-primitives 1.2.0", diff --git a/crates/op-rbuilder/Cargo.toml b/crates/op-rbuilder/Cargo.toml index 5b6fbd23..9cba3581 100644 --- a/crates/op-rbuilder/Cargo.toml +++ b/crates/op-rbuilder/Cargo.toml @@ -133,8 +133,8 @@ tar = { version = "0.4", optional = true } ctor = { version = "0.4.2", optional = true } rlimit = { version = "0.10", optional = true } macros = { path = "src/tests/framework/macros", optional = true } -pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "05b3f123d165de2b60c70621f40c7c3a6b1a9b07" } -pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "05b3f123d165de2b60c70621f40c7c3a6b1a9b07" } +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "7955edcec2198d95286409a72256efcac0d1e3bc" } +pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "7955edcec2198d95286409a72256efcac0d1e3bc" } itertools = "0.14.0" [target.'cfg(unix)'.dependencies] diff --git a/crates/op-rbuilder/src/builders/pod/payload.rs b/crates/op-rbuilder/src/builders/pod/payload.rs index e7778ef7..abdff799 100644 --- a/crates/op-rbuilder/src/builders/pod/payload.rs +++ b/crates/op-rbuilder/src/builders/pod/payload.rs @@ -133,17 +133,22 @@ where cancel: CancellationToken::new(), }; + let span = tracing::info_span!("build_payload", block_number); + let _enter = span.enter(); + self.build_payload(args, |timestamp, attrs| { let pod_client = self.pod_client.clone(); let handle = self.executor.handle().clone(); + let span = span.clone(); let txs = std::thread::spawn(move || { + let _enter = span.enter(); handle.block_on(pod_client.best_transactions(timestamp, attrs)) }) .join() .unwrap() .unwrap(); - info!(target: "payload_builder", block=block_number, len=txs.len(), "fetched best transactions"); + info!(target: "payload_builder", len=txs.len(), "fetched best transactions"); txs }) } diff --git a/crates/op-rbuilder/src/builders/pod/pod_client.rs b/crates/op-rbuilder/src/builders/pod/pod_client.rs index 3dfb5c31..25e55dfa 100644 --- a/crates/op-rbuilder/src/builders/pod/pod_client.rs +++ b/crates/op-rbuilder/src/builders/pod/pod_client.rs @@ -1,5 +1,6 @@ use std::{collections::VecDeque, fmt::Debug}; +use alloy_consensus::Transaction; use alloy_primitives::Address; use alloy_rlp::Decodable; use itertools::Itertools; @@ -27,23 +28,28 @@ impl PodClient { Ok(Self { client, rpc_url }) } + #[tracing::instrument(skip(self, _attrs))] pub async fn best_transactions( &self, timestamp_secs: u64, _attrs: BestTransactionsAttributes, ) -> eyre::Result { - let timestamp = timestamp_secs - 2; - tracing::trace!(target: "payload_builder", timestamp, "querying best transactions"); - let bids = self.client.bids(timestamp).await.unwrap_or_else(|err| { - tracing::error!(target: "payload_builder", ?err, "failed to fetch bids from pod"); - Vec::new() - }); + let auction_deadline = timestamp_secs - 2; + tracing::trace!(target: "payload_builder", auction_deadline, "querying best transactions"); + let bids = self + .client + .bids(auction_deadline) + .await + .unwrap_or_else(|err| { + tracing::error!(target: "payload_builder", ?err, "failed to fetch bids from pod"); + Vec::new() + }); let transactions = bids .into_iter() - .sorted_by_key(|bid| { - // Sort by the bid amount in descending order - -bid.amount + .sorted_unstable_by_key(|bid| { + bid.amount }) + .rev() .filter_map(|bid| { let recovered = match Recovered::::decode(&mut bid.data.as_slice()) { @@ -56,6 +62,9 @@ impl PodClient { None } }?; + if recovered.max_priority_fee_per_gas().unwrap_or(0) != bid.amount { + tracing::error!(target: "payload_builder", tx=%recovered.tx_hash(), "ignoring tx with different max priority fee per gas than bid amount"); + } Some(OpPooledTransaction::new(recovered, bid.data.len()).into()) }) From 88e82cb2e63522d54640d692eb8107827bad184a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Tue, 22 Jul 2025 13:30:24 +0200 Subject: [PATCH 5/8] bump pod-sdk to work with latest devnet --- Cargo.lock | 105 +++++++--------------------------- crates/op-rbuilder/Cargo.toml | 4 +- 2 files changed, 23 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30369a96..4aee6981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.6", + "crypto-common", "generic-array", ] @@ -461,7 +461,7 @@ dependencies = [ "ruint", "rustc-hash 2.1.1", "serde", - "sha3 0.10.8", + "sha3", "tiny-keccak", ] @@ -492,7 +492,7 @@ dependencies = [ "ruint", "rustc-hash 2.1.1", "serde", - "sha3 0.10.8", + "sha3", "tiny-keccak", ] @@ -1903,15 +1903,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.11.0-rc.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a229bfd78e4827c91b9b95784f69492c1b77c1ab75a45a8a037b139215086f94" -dependencies = [ - "hybrid-array", -] - [[package]] name = "block-padding" version = "0.3.3" @@ -2374,7 +2365,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.6", + "crypto-common", "inout", ] @@ -2574,12 +2565,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "const-oid" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" - [[package]] name = "const_format" version = "0.2.34" @@ -2777,15 +2762,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a23fa214dea9efd4dacee5a5614646b30216ae0f05d4bb51bafb50e9da1c5be" -dependencies = [ - "hybrid-array", -] - [[package]] name = "ctor" version = "0.4.2" @@ -2938,7 +2914,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "sha3 0.10.8", + "sha3", "time", "x509-parser", ] @@ -2966,7 +2942,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid 0.9.6", + "const-oid", "pem-rfc7468", "zeroize", ] @@ -3103,22 +3079,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid 0.9.6", - "crypto-common 0.1.6", + "const-oid", + "crypto-common", "subtle", ] -[[package]] -name = "digest" -version = "0.11.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460dd7f37e4950526b54a5a6b1f41b6c8e763c58eb9a8fc8fc05ba5c2f44ca7b" -dependencies = [ - "block-buffer 0.11.0-rc.4", - "const-oid 0.10.1", - "crypto-common 0.2.0-rc.3", -] - [[package]] name = "dirs" version = "5.0.1" @@ -3375,7 +3340,7 @@ dependencies = [ "rand 0.8.5", "secp256k1", "serde", - "sha3 0.10.8", + "sha3", "zeroize", ] @@ -4216,15 +4181,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hybrid-array" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d15931895091dea5c47afa5b3c9a01ba634b311919fd4d41388fa0e3d76af" -dependencies = [ - "typenum", -] - [[package]] name = "hyper" version = "1.6.0" @@ -5198,15 +5154,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "keccak" -version = "0.2.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cdd4f0dc5807b9a2b25dd48a3f58e862606fe7bd47f41ecde36e97422d7e90" -dependencies = [ - "cpufeatures", -] - [[package]] name = "keccak-asm" version = "0.1.4" @@ -6310,7 +6257,7 @@ dependencies = [ "serde_json", "serde_with", "serde_yaml", - "sha3 0.10.8", + "sha3", "shellexpand", "tar", "tdx", @@ -6564,7 +6511,7 @@ dependencies = [ [[package]] name = "optimism-tx-auction" version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" +source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" dependencies = [ "alloy", "anyhow", @@ -6875,8 +6822,8 @@ dependencies = [ [[package]] name = "pod-sdk" -version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" +version = "0.1.6" +source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6901,8 +6848,8 @@ dependencies = [ [[package]] name = "pod-types" -version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=7955edcec2198d95286409a72256efcac0d1e3bc#7955edcec2198d95286409a72256efcac0d1e3bc" +version = "0.1.6" +source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" dependencies = [ "alloy-consensus", "alloy-primitives 1.2.0", @@ -6911,15 +6858,15 @@ dependencies = [ "alloy-signer-local", "alloy-sol-types 1.2.0", "anyhow", - "async-trait", "base64 0.22.1", "bytes", "hex", "itertools 0.13.0", - "k256", "serde", - "sha3 0.11.0-rc.0", + "serde_with", + "thiserror 2.0.12", "tokio", + "tracing", "utoipa", ] @@ -8100,7 +8047,7 @@ dependencies = [ "reth-network-peers", "secp256k1", "sha2 0.10.9", - "sha3 0.10.8", + "sha3", "thiserror 2.0.12", "tokio", "tokio-stream", @@ -11377,17 +11324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ "digest 0.10.7", - "keccak 0.1.5", -] - -[[package]] -name = "sha3" -version = "0.11.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e6a92fd180fd205defdc0b78288ce847c7309d329fd6647a814567e67db50e" -dependencies = [ - "digest 0.11.0-rc.0", - "keccak 0.2.0-pre.0", + "keccak", ] [[package]] @@ -12648,7 +12585,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.6", + "crypto-common", "subtle", ] diff --git a/crates/op-rbuilder/Cargo.toml b/crates/op-rbuilder/Cargo.toml index 9cba3581..fc0a94ba 100644 --- a/crates/op-rbuilder/Cargo.toml +++ b/crates/op-rbuilder/Cargo.toml @@ -133,8 +133,8 @@ tar = { version = "0.4", optional = true } ctor = { version = "0.4.2", optional = true } rlimit = { version = "0.10", optional = true } macros = { path = "src/tests/framework/macros", optional = true } -pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "7955edcec2198d95286409a72256efcac0d1e3bc" } -pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "7955edcec2198d95286409a72256efcac0d1e3bc" } +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "559af82085010319f74cb74e84938394d1e96842" } +pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "559af82085010319f74cb74e84938394d1e96842" } itertools = "0.14.0" [target.'cfg(unix)'.dependencies] From 1d673c25c8ea8de2af83019e86d240755662545a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 24 Jul 2025 14:24:17 +0200 Subject: [PATCH 6/8] bump pod auction --- Cargo.lock | 7 ++++--- crates/op-rbuilder/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4aee6981..84fadc24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6511,11 +6511,12 @@ dependencies = [ [[package]] name = "optimism-tx-auction" version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" +source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" dependencies = [ "alloy", "anyhow", "clap 4.5.40", + "futures", "humantime", "op-alloy", "pod-sdk", @@ -6823,7 +6824,7 @@ dependencies = [ [[package]] name = "pod-sdk" version = "0.1.6" -source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" +source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6849,7 +6850,7 @@ dependencies = [ [[package]] name = "pod-types" version = "0.1.6" -source = "git+https://github.com/podnetwork/pod-sdk?rev=559af82085010319f74cb74e84938394d1e96842#559af82085010319f74cb74e84938394d1e96842" +source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" dependencies = [ "alloy-consensus", "alloy-primitives 1.2.0", diff --git a/crates/op-rbuilder/Cargo.toml b/crates/op-rbuilder/Cargo.toml index fc0a94ba..45dfcc36 100644 --- a/crates/op-rbuilder/Cargo.toml +++ b/crates/op-rbuilder/Cargo.toml @@ -133,8 +133,8 @@ tar = { version = "0.4", optional = true } ctor = { version = "0.4.2", optional = true } rlimit = { version = "0.10", optional = true } macros = { path = "src/tests/framework/macros", optional = true } -pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "559af82085010319f74cb74e84938394d1e96842" } -pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "559af82085010319f74cb74e84938394d1e96842" } +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" } +pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" } itertools = "0.14.0" [target.'cfg(unix)'.dependencies] From f104e3b1dde66571daa48d101ad016fed77deea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Wed, 13 Aug 2025 13:09:23 +0200 Subject: [PATCH 7/8] use auction client from pod SDK --- Cargo.lock | 150 +++++++++--------- Cargo.toml | 3 +- crates/op-rbuilder/Cargo.toml | 3 +- .../op-rbuilder/src/builders/pod/payload.rs | 9 +- .../src/builders/pod/pod_client.rs | 65 +++++--- 5 files changed, 126 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cfa241bf..17fe675b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.0.20" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae58d888221eecf621595e2096836ce7cfc37be06bfa39d7f64aa6a3ea4c9e5b" +checksum = "48dff4dd98e17de00203f851800bbc8b76eb29a4d4e3e44074614338b7a3308d" dependencies = [ "alloy-consensus", "alloy-contract", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6093bc69509849435a2d68237a2e9fea79d27390c8e62f1e4012c460aabad8" +checksum = "eda689f7287f15bd3582daba6be8d1545bad3740fd1fb778f629a1fe866bb43b" dependencies = [ "alloy-eips", "alloy-primitives 1.3.0", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1cfed4fefd13b5620cb81cdb6ba397866ff0de514c1b24806e6e79cdff5570" +checksum = "2b5659581e41e8fe350ecc3593cb5c9dcffddfd550896390f2b78a07af67b0fa" dependencies = [ "alloy-consensus", "alloy-eips", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28074a21cd4f7c3a7ab218c4f38fae6be73944e1feae3b670c68b60bf85ca40" +checksum = "944085cf3ac8f32d96299aa26c03db7c8ca6cdaafdbc467910b889f0328e6b70" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -269,9 +269,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5937e2d544e9b71000942d875cbc57965b32859a666ea543cc57aae5a06d602d" +checksum = "6f35887da30b5fc50267109a3c61cd63e6ca1f45967983641053a40ee83468c1" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -332,9 +332,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51b4c13e02a8104170a4de02ccf006d7c233e6c10ab290ee16e7041e6ac221d" +checksum = "11d4009efea6f403b3a80531f9c6f70fc242399498ff71196a1688cc1c901f44" dependencies = [ "alloy-eips", "alloy-primitives 1.3.0", @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b590caa6b6d8bc10e6e7a7696c59b1e550e89f27f50d1ee13071150d3a3e3f66" +checksum = "883dee3b4020fcb5667ee627b4f401e899dad82bf37b246620339dd980720ed9" dependencies = [ "alloy-primitives 1.3.0", "alloy-sol-types 1.3.0", @@ -399,9 +399,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36fe5af1fca03277daa56ad4ce5f6d623d3f4c2273ea30b9ee8674d18cefc1fa" +checksum = "cd6e5b8ac1654a05c224390008e43634a2bdc74e181e02cf8ed591d8b3d4ad08" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -425,9 +425,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793df1e3457573877fbde8872e4906638fde565ee2d3bd16d04aad17d43dbf0e" +checksum = "80d7980333dd9391719756ac28bc2afa9baa705fc70ffd11dc86ab078dd64477" dependencies = [ "alloy-consensus", "alloy-eips", @@ -541,9 +541,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59879a772ebdcde9dc4eb38b2535d32e8503d3175687cc09e763a625c5fcf32" +checksum = "478a42fe167057b7b919cd8b0c2844f0247f667473340dad100eaf969de5754e" dependencies = [ "alloy-chains", "alloy-consensus", @@ -570,7 +570,6 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "http", "lru 0.13.0", "parking_lot", "pin-project", @@ -586,13 +585,14 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdfb2899b54b7cb0063fa8e61938320f9be6b81b681be69c203abf130a87baa" +checksum = "b0a99b17987f40a066b29b6b56d75e84cd193b866cac27cae17b59f40338de95" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.3.0", "alloy-transport", + "auto_impl", "bimap", "futures", "parking_lot", @@ -629,9 +629,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f060e3bb9f319eb01867a2d6d1ff9e0114e8877f5ca8f5db447724136106cae" +checksum = "8a0c6d723fbdf4a87454e2e3a275e161be27edcfbf46e2e3255dd66c138634b6" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.3.0", @@ -655,9 +655,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d47b637369245d2dafef84b223b1ff5ea59e6cd3a98d2d3516e32788a0b216df" +checksum = "c41492dac39365b86a954de86c47ec23dcc7452cdb2fde591caadc194b3e34c6" dependencies = [ "alloy-primitives 1.3.0", "alloy-rpc-types-engine", @@ -692,9 +692,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e26b4dd90b33bd158975307fb9cf5fafa737a0e33cbb772a8648bf8be13c104" +checksum = "8f7eb22670a972ad6c222a6c6dac3eef905579acffe9d63ab42be24c7d158535" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -731,9 +731,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f9cbf5f781b9ee39cfdddea078fdef6015424f4c8282ef0e5416d15ca352c4" +checksum = "e24c171377c0684e3860385f6d93fbfcc8ecc74f6cce8304c822bf1a50bacce0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46586ec3c278639fc0e129f0eb73dbfa3d57f683c44b2ff5e066fab7ba63fa1f" +checksum = "b777b98526bbe5b7892ca22a7fd5f18ed624ff664a79f40d0f9f2bf94ba79a84" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -802,9 +802,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aaf142f4f6c0bdd06839c422179bae135024407d731e6f365380f88cd4730e" +checksum = "3cc803e9b8d16154c856a738c376e002abe4b388e5fef91c8aebc8373e99fd45" dependencies = [ "alloy-primitives 1.3.0", "alloy-rpc-types-eth", @@ -814,9 +814,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1722bc30feef87cc0fa824e43c9013f9639cc6c037be7be28a31361c788be2" +checksum = "ee8d2c52adebf3e6494976c8542fbdf12f10123b26e11ad56f77274c16a2a039" dependencies = [ "alloy-primitives 1.3.0", "arbitrary", @@ -826,9 +826,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3674beb29e68fbbc7be302b611cf35fe07b736e308012a280861df5a2361395" +checksum = "7c0494d1e0f802716480aabbe25549c7f6bc2a25ff33b08fd332bbb4b7d06894" dependencies = [ "alloy-primitives 1.3.0", "async-trait", @@ -841,9 +841,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad7094c39cd41b03ed642145b0bd37251e31a9cf2ed19e1ce761f089867356a6" +checksum = "59c2435eb8979a020763ced3fb478932071c56e5f75ea86db41f320915d325ba" dependencies = [ "alloy-consensus", "alloy-network", @@ -1001,12 +1001,13 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89bec2f59a41c0e259b6fe92f78dfc49862c17d10f938db9c33150d5a7f42b6" +checksum = "3c0107675e10c7f248bf7273c1e7fdb02409a717269cc744012e6f3c39959bfb" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.3.0", + "auto_impl", "base64 0.22.1", "derive_more", "futures", @@ -1024,9 +1025,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3615ec64d775fec840f4e9d5c8e1f739eb1854d8d28db093fb3d4805e0cb53" +checksum = "78e3736701b5433afd06eecff08f0688a71a10e0e1352e0bbf0bed72f0dd4e35" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -1039,9 +1040,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374db72669d8ee09063b9aa1a316e812d5cdfce7fc9a99a3eceaa0e5512300d2" +checksum = "c79064b5a08259581cb5614580010007c2df6deab1e8f3e8c7af8d7e9227008f" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -1059,9 +1060,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5dbaa6851875d59c8803088f4b6ec72eaeddf7667547ae8995c1a19fbca6303" +checksum = "77fd607158cb9bc54cbcfcaab4c5f36c5b26994c7dc58b6f095ce27a54f270f3" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -1097,9 +1098,9 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f916ff6d52f219c44a9684aea764ce2c7e1d53bd4a724c9b127863aeacc30bb" +checksum = "6acb36318dfa50817154064fea7932adf2eec3f51c86680e2b37d7e8906c66bb" dependencies = [ "alloy-primitives 1.3.0", "darling", @@ -6333,7 +6334,6 @@ dependencies = [ "op-alloy-rpc-types-engine", "op-revm 8.0.3", "opentelemetry 0.29.1", - "optimism-tx-auction", "parking_lot", "pod-sdk", "rand 0.9.1", @@ -6654,24 +6654,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "optimism-tx-auction" -version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" -dependencies = [ - "alloy", - "anyhow", - "clap 4.5.40", - "futures", - "humantime", - "op-alloy", - "pod-sdk", - "pod-types", - "rand 0.9.1", - "tokio", - "tracing", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -6986,43 +6968,53 @@ dependencies = [ "crunchy", ] +[[package]] +name = "pod-examples-solidity" +version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk?rev=cab43b2075fb683f3eb5c34cf7b738f420b0c31d#cab43b2075fb683f3eb5c34cf7b738f420b0c31d" +dependencies = [ + "alloy", + "serde", +] + [[package]] name = "pod-sdk" version = "0.1.6" -source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" +source = "git+https://github.com/podnetwork/pod-sdk?rev=1c665bb9926960c83f3253ced3f3af2b972f7657#1c665bb9926960c83f3253ced3f3af2b972f7657" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network", - "alloy-primitives 1.2.0", + "alloy-primitives 1.3.0", "alloy-provider", "alloy-pubsub", "alloy-rpc-types", "alloy-signer", "alloy-signer-local", - "alloy-sol-types 1.2.0", + "alloy-sol-types 1.3.0", "alloy-transport", - "alloy-transport-http", "anyhow", "async-trait", "futures", "hex", + "pod-examples-solidity", "pod-types", "serde", + "tracing", ] [[package]] name = "pod-types" version = "0.1.6" -source = "git+https://github.com/podnetwork/pod-sdk?rev=8f39e51f0cd0c0e02e8b6011562f59f6b60988bb#8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" +source = "git+https://github.com/podnetwork/pod-sdk?rev=1c665bb9926960c83f3253ced3f3af2b972f7657#1c665bb9926960c83f3253ced3f3af2b972f7657" dependencies = [ "alloy-consensus", - "alloy-primitives 1.2.0", + "alloy-primitives 1.3.0", "alloy-rpc-types", "alloy-signer", "alloy-signer-local", - "alloy-sol-types 1.2.0", + "alloy-sol-types 1.3.0", "anyhow", "base64 0.22.1", "bytes", @@ -14026,7 +14018,7 @@ version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "serde", "serde_json", "utoipa-gen", @@ -14040,7 +14032,7 @@ checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1c1d32d8..28b02453 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/flashbots/op-rbuilder" exclude = [".github/"] [workspace] -members = [ "crates/op-rbuilder", "crates/tdx-quote-provider"] +members = ["crates/op-rbuilder", "crates/tdx-quote-provider"] default-members = ["crates/op-rbuilder"] resolver = "2" @@ -140,6 +140,7 @@ alloy-rpc-types-eth = { version = "1.0.23" } alloy-signer-local = { version = "1.0.23" } alloy-rpc-client = { version = "1.0.23" } alloy-genesis = { version = "1.0.23" } +alloy-rlp = { version = "0.3.12" } alloy-trie = { version = "0.9.0" } # optimism diff --git a/crates/op-rbuilder/Cargo.toml b/crates/op-rbuilder/Cargo.toml index 5d93e9e0..374d73a5 100644 --- a/crates/op-rbuilder/Cargo.toml +++ b/crates/op-rbuilder/Cargo.toml @@ -133,8 +133,7 @@ ctor = { version = "0.4.2", optional = true } rlimit = { version = "0.10", optional = true } macros = { path = "src/tests/framework/macros", optional = true } testcontainers = "0.24.0" -pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" } -pod-auction = { package = "optimism-tx-auction", git = "https://github.com/podnetwork/pod-sdk", rev = "8f39e51f0cd0c0e02e8b6011562f59f6b60988bb" } +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk", rev = "1c665bb9926960c83f3253ced3f3af2b972f7657" } itertools = "0.14.0" [target.'cfg(unix)'.dependencies] diff --git a/crates/op-rbuilder/src/builders/pod/payload.rs b/crates/op-rbuilder/src/builders/pod/payload.rs index abdff799..c5098ff1 100644 --- a/crates/op-rbuilder/src/builders/pod/payload.rs +++ b/crates/op-rbuilder/src/builders/pod/payload.rs @@ -136,13 +136,13 @@ where let span = tracing::info_span!("build_payload", block_number); let _enter = span.enter(); - self.build_payload(args, |timestamp, attrs| { + self.build_payload(args, |timestamp, _attrs| { let pod_client = self.pod_client.clone(); let handle = self.executor.handle().clone(); let span = span.clone(); let txs = std::thread::spawn(move || { let _enter = span.enter(); - handle.block_on(pod_client.best_transactions(timestamp, attrs)) + handle.block_on(pod_client.best_transactions(timestamp)) }) .join() .unwrap() @@ -248,6 +248,7 @@ where cancel, builder_signer: self.config.builder_signer, metrics: self.metrics.clone(), + extra_ctx: Default::default(), }; let builder = OpBuilder::new(best); @@ -325,7 +326,7 @@ impl Txs> O ctx: &OpPayloadBuilderCtx, ) -> Result, PayloadBuilderError> where - DB: Database + AsRef

, + DB: Database + AsRef

+ std::fmt::Debug, P: StorageRootProvider, { let Self { best } = self; @@ -423,7 +424,7 @@ impl Txs> O ctx: OpPayloadBuilderCtx, ) -> Result, PayloadBuilderError> where - DB: Database + AsRef

, + DB: Database + AsRef

+ std::fmt::Debug, P: StateRootProvider + HashedPostStateProvider + StorageRootProvider, { let ExecutedPayload { info } = match self.execute(&mut state, &ctx)? { diff --git a/crates/op-rbuilder/src/builders/pod/pod_client.rs b/crates/op-rbuilder/src/builders/pod/pod_client.rs index 25e55dfa..95b7e5f3 100644 --- a/crates/op-rbuilder/src/builders/pod/pod_client.rs +++ b/crates/op-rbuilder/src/builders/pod/pod_client.rs @@ -1,44 +1,73 @@ -use std::{collections::VecDeque, fmt::Debug}; +use std::{collections::VecDeque, fmt::Debug, time::Duration}; +use eyre::Context; use alloy_consensus::Transaction; -use alloy_primitives::Address; +use alloy_primitives::{Address, U256}; use alloy_rlp::Decodable; use itertools::Itertools; -use pod_auction::client::AuctionClient; +use pod_sdk::{auctions::client::AuctionClient, provider::PodProviderBuilder}; use reth_optimism_primitives::OpTransactionSigned; use reth_optimism_txpool::OpPooledTransaction; use reth_payload_util::PayloadTransactions; use reth_primitives::Recovered; -use reth_transaction_pool::BestTransactionsAttributes; +use tokio::sync::OnceCell; use crate::tx::FBPooledTransaction; pub(super) struct PodClient { - client: AuctionClient, + client: OnceCell, rpc_url: String, + contract: Address, } #[derive(Debug)] pub(super) struct Transactions(VecDeque); impl PodClient { - pub async fn new(rpc_url: String, contract_address: Address) -> eyre::Result { - let client = AuctionClient::new(rpc_url.clone(), contract_address).await; + pub async fn new(rpc_url: String, contract: Address) -> eyre::Result { + Ok(Self { + client: OnceCell::new(), + rpc_url, + contract, + }) + } + + async fn get_client(&self) -> eyre::Result<&AuctionClient> { + self.client + .get_or_try_init(|| async { + let provider = PodProviderBuilder::new() + .on_url(self.rpc_url.clone()) + .await + .map_err(eyre::Error::from)?; - Ok(Self { client, rpc_url }) + Ok(AuctionClient::new(provider, self.contract)) + }) + .await } - #[tracing::instrument(skip(self, _attrs))] - pub async fn best_transactions( - &self, - timestamp_secs: u64, - _attrs: BestTransactionsAttributes, - ) -> eyre::Result { + #[tracing::instrument(skip(self))] + pub async fn best_transactions(&self, timestamp_secs: u64) -> eyre::Result { + let auction = self.get_client().await?; let auction_deadline = timestamp_secs - 2; tracing::trace!(target: "payload_builder", auction_deadline, "querying best transactions"); - let bids = self - .client - .bids(auction_deadline) + let auction_deadline = pod_sdk::Timestamp::from_seconds(auction_deadline); + + tracing::info!("waiting for past perfect time"); + // FIXME: The current PPT implementation in pod is dummy and waits 5s which is far too long. + // Use auction.wait_for_auction_end() when it's fixed. + auction + .auction + .provider() + .wait_past_perfect_time( + auction_deadline - Duration::from_secs(5) + Duration::from_millis(200), + ) + .await + .context("waiting for auction end (past perfect time)")?; + tracing::info!("past perfect time reached"); + + let bids = auction + .fetch_bids_for_deadline(auction_deadline.into()) + // .fetch_bids(U256::from(auction_deadline )) // auction ID is in microseconds .await .unwrap_or_else(|err| { tracing::error!(target: "payload_builder", ?err, "failed to fetch bids from pod"); @@ -62,7 +91,7 @@ impl PodClient { None } }?; - if recovered.max_priority_fee_per_gas().unwrap_or(0) != bid.amount { + if U256::from(recovered.max_priority_fee_per_gas().unwrap_or(0)) != bid.amount { tracing::error!(target: "payload_builder", tx=%recovered.tx_hash(), "ignoring tx with different max priority fee per gas than bid amount"); } From 91efb23aea757a63a3f36e0e29579a79f2b8fde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Mon, 25 Aug 2025 12:49:15 +0200 Subject: [PATCH 8/8] default to auctions on pod public devnet --- crates/op-rbuilder/src/args/op.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/op-rbuilder/src/args/op.rs b/crates/op-rbuilder/src/args/op.rs index 271ed5d8..2f86aae3 100644 --- a/crates/op-rbuilder/src/args/op.rs +++ b/crates/op-rbuilder/src/args/op.rs @@ -161,14 +161,14 @@ pub struct PodArgs { #[arg( long = "pod.rpc-url", env = "POD_RPC_URL", - default_value = "ws://127.0.0.1:8545" + default_value = "wss://rpc.v2.pod.network" )] pub pod_rpc_url: String, #[arg( long = "pod.contract-address", env = "POD_CONTRACT_ADDRESS", - default_value = "0x12296f2D128530a834460DF6c36a2895B793F26d" + default_value = "0xedd0670497e00ded712a398563ea938a29dd28c7" )] pub pod_contract_address: Address, }