From c96872be409964afe2bcca694f7dfaedd24baa7d Mon Sep 17 00:00:00 2001 From: Himess <95512809+Himess@users.noreply.github.com> Date: Tue, 13 Jan 2026 22:44:34 +0300 Subject: [PATCH] chore(builder): enable repository formatting Remove builder crates from rustfmt.toml ignore list and apply repository-wide formatting to all builder crates (op-rbuilder, p2p, tdx-quote-provider). This aligns the builder code with the rest of the repository's formatting conventions. Closes #378 --- crates/builder/op-rbuilder/build.rs | 6 +- crates/builder/op-rbuilder/src/args/mod.rs | 9 +- crates/builder/op-rbuilder/src/args/op.rs | 84 ++--- .../op-rbuilder/src/args/playground.rs | 50 ++- .../op-rbuilder/src/bin/tester/main.rs | 4 +- .../op-rbuilder/src/builders/builder_tx.rs | 56 +--- .../op-rbuilder/src/builders/context.rs | 89 ++--- .../src/builders/flashblocks/best_txs.rs | 19 +- .../src/builders/flashblocks/builder_tx.rs | 15 +- .../src/builders/flashblocks/config.rs | 7 +- .../src/builders/flashblocks/ctx.rs | 18 +- .../src/builders/flashblocks/mod.rs | 5 +- .../src/builders/flashblocks/p2p.rs | 6 +- .../src/builders/flashblocks/payload.rs | 305 ++++++------------ .../builders/flashblocks/payload_handler.rs | 89 ++--- .../src/builders/flashblocks/service.rs | 47 ++- .../src/builders/flashblocks/wspub.rs | 18 +- .../op-rbuilder/src/builders/generator.rs | 57 +--- .../builder/op-rbuilder/src/builders/mod.rs | 4 +- .../src/builders/standard/builder_tx.rs | 8 +- .../src/builders/standard/payload.rs | 166 +++------- .../src/builders/standard/service.rs | 3 +- .../op-rbuilder/src/flashtestations/args.rs | 15 +- .../src/flashtestations/attestation.rs | 17 +- .../src/flashtestations/builder_tx.rs | 46 +-- .../src/flashtestations/service.rs | 33 +- .../src/flashtestations/tx_manager.rs | 39 +-- .../op-rbuilder/src/gas_limiter/args.rs | 12 +- .../op-rbuilder/src/gas_limiter/error.rs | 6 +- .../op-rbuilder/src/gas_limiter/metrics.rs | 3 +- .../op-rbuilder/src/gas_limiter/mod.rs | 30 +- crates/builder/op-rbuilder/src/launcher.rs | 38 +-- crates/builder/op-rbuilder/src/metrics.rs | 18 +- crates/builder/op-rbuilder/src/mock_tx.rs | 91 ++---- .../op-rbuilder/src/monitor_tx_pool.rs | 13 +- .../op-rbuilder/src/primitives/bundle.rs | 108 ++----- .../src/primitives/reth/engine_api_builder.rs | 57 ++-- .../src/primitives/reth/execution.rs | 3 +- .../op-rbuilder/src/primitives/telemetry.rs | 3 +- .../op-rbuilder/src/revert_protection.rs | 35 +- .../builder/op-rbuilder/src/tests/backrun.rs | 109 ++----- .../src/tests/data_availability.rs | 47 +-- .../op-rbuilder/src/tests/flashblocks.rs | 140 ++------ .../op-rbuilder/src/tests/flashtestations.rs | 104 ++---- crates/builder/op-rbuilder/src/tests/forks.rs | 36 +-- .../op-rbuilder/src/tests/framework/apis.rs | 23 +- .../src/tests/framework/contracts.rs | 6 +- .../op-rbuilder/src/tests/framework/driver.rs | 25 +- .../src/tests/framework/external.rs | 68 +--- .../src/tests/framework/instance.rs | 111 +++---- .../src/tests/framework/macros/src/lib.rs | 11 +- .../op-rbuilder/src/tests/framework/mod.rs | 4 +- .../op-rbuilder/src/tests/framework/txs.rs | 69 ++-- .../op-rbuilder/src/tests/framework/utils.rs | 95 ++---- .../op-rbuilder/src/tests/gas_limiter.rs | 23 +- .../op-rbuilder/src/tests/miner_gas_limit.rs | 53 +-- .../builder/op-rbuilder/src/tests/ordering.rs | 8 +- .../builder/op-rbuilder/src/tests/revert.rs | 111 ++----- crates/builder/op-rbuilder/src/tests/smoke.rs | 34 +- .../builder/op-rbuilder/src/tests/txpool.rs | 13 +- crates/builder/op-rbuilder/src/tx.rs | 4 +- .../builder/op-rbuilder/src/tx_data_store.rs | 82 ++--- crates/builder/op-rbuilder/src/tx_signer.rs | 43 +-- crates/builder/p2p/src/behaviour.rs | 12 +- crates/builder/p2p/src/lib.rs | 85 ++--- crates/builder/p2p/src/outgoing.rs | 35 +- crates/builder/tdx-quote-provider/src/main.rs | 8 +- .../tdx-quote-provider/src/provider.rs | 8 +- .../builder/tdx-quote-provider/src/server.rs | 38 +-- .../tdx-quote-provider/tests/simple.rs | 8 +- rustfmt.toml | 5 - 71 files changed, 905 insertions(+), 2145 deletions(-) diff --git a/crates/builder/op-rbuilder/build.rs b/crates/builder/op-rbuilder/build.rs index 97acc1fe..850a4b6b 100644 --- a/crates/builder/op-rbuilder/build.rs +++ b/crates/builder/op-rbuilder/build.rs @@ -22,6 +22,7 @@ // THE SOFTWARE. use std::{env, error::Error}; + use vergen::{BuildBuilder, CargoBuilder, Emitter}; use vergen_git2::Git2Builder; @@ -32,10 +33,7 @@ fn main() -> Result<(), Box> { emitter.add_instructions(&build_builder)?; - let cargo_builder = CargoBuilder::default() - .features(true) - .target_triple(true) - .build()?; + let cargo_builder = CargoBuilder::default().features(true).target_triple(true).build()?; emitter.add_instructions(&cargo_builder)?; diff --git a/crates/builder/op-rbuilder/src/args/mod.rs b/crates/builder/op-rbuilder/src/args/mod.rs index 587cce8a..c849a085 100644 --- a/crates/builder/op-rbuilder/src/args/mod.rs +++ b/crates/builder/op-rbuilder/src/args/mod.rs @@ -1,12 +1,13 @@ -use crate::{ - builders::BuilderMode, - metrics::{LONG_VERSION, SHORT_VERSION}, -}; use clap_builder::{CommandFactory, FromArgMatches}; pub use op::{FlashblocksArgs, OpRbuilderArgs, TelemetryArgs}; use playground::PlaygroundOptions; use reth_optimism_cli::{chainspec::OpChainSpecParser, commands::Commands}; +use crate::{ + builders::BuilderMode, + metrics::{LONG_VERSION, SHORT_VERSION}, +}; + mod op; mod playground; diff --git a/crates/builder/op-rbuilder/src/args/op.rs b/crates/builder/op-rbuilder/src/args/op.rs index 4282d54d..d7d01e08 100644 --- a/crates/builder/op-rbuilder/src/args/op.rs +++ b/crates/builder/op-rbuilder/src/args/op.rs @@ -4,16 +4,18 @@ //! clap [Args](clap::Args) for optimism rollup configuration -use crate::{ - flashtestations::args::FlashtestationsArgs, gas_limiter::args::GasLimiterArgs, - tx_signer::Signer, -}; +use std::path::PathBuf; + use alloy_primitives::Address; use anyhow::{Result, anyhow}; use clap::Parser; use reth_optimism_cli::commands::Commands; use reth_optimism_node::args::RollupArgs; -use std::path::PathBuf; + +use crate::{ + flashtestations::args::FlashtestationsArgs, gas_limiter::args::GasLimiterArgs, + tx_signer::Signer, +}; /// Parameters for rollup configuration #[derive(Debug, Clone, PartialEq, Eq, clap::Args)] @@ -27,11 +29,7 @@ pub struct OpRbuilderArgs { pub builder_signer: Option, /// chain block time in milliseconds - #[arg( - long = "rollup.chain-block-time", - default_value = "1000", - env = "CHAIN_BLOCK_TIME" - )] + #[arg(long = "rollup.chain-block-time", default_value = "1000", env = "CHAIN_BLOCK_TIME")] pub chain_block_time: u64, /// max gas a transaction can use @@ -78,9 +76,7 @@ pub struct OpRbuilderArgs { impl Default for OpRbuilderArgs { fn default() -> Self { let args = crate::args::Cli::parse_from(["dummy", "node"]); - let Commands::Node(node_command) = args.command else { - unreachable!() - }; + let Commands::Node(node_command) = args.command else { unreachable!() }; node_command.ext } } @@ -104,56 +100,32 @@ pub struct FlashblocksArgs { /// /// The default value will change in the future once the flashblocks /// feature is stable. - #[arg( - long = "flashblocks.enabled", - default_value = "false", - env = "ENABLE_FLASHBLOCKS" - )] + #[arg(long = "flashblocks.enabled", default_value = "false", env = "ENABLE_FLASHBLOCKS")] pub enabled: bool, /// The port that we bind to for the websocket server that provides flashblocks - #[arg( - long = "flashblocks.port", - env = "FLASHBLOCKS_WS_PORT", - default_value = "1111" - )] + #[arg(long = "flashblocks.port", env = "FLASHBLOCKS_WS_PORT", default_value = "1111")] pub flashblocks_port: u16, /// The address that we bind to for the websocket server that provides flashblocks - #[arg( - long = "flashblocks.addr", - env = "FLASHBLOCKS_WS_ADDR", - default_value = "127.0.0.1" - )] + #[arg(long = "flashblocks.addr", env = "FLASHBLOCKS_WS_ADDR", default_value = "127.0.0.1")] pub flashblocks_addr: String, /// flashblock block time in milliseconds - #[arg( - long = "flashblocks.block-time", - default_value = "250", - env = "FLASHBLOCK_BLOCK_TIME" - )] + #[arg(long = "flashblocks.block-time", default_value = "250", env = "FLASHBLOCK_BLOCK_TIME")] pub flashblocks_block_time: u64, /// Builder would always thry to produce fixed number of flashblocks without regard to time of /// FCU arrival. /// In cases of late FCU it could lead to partially filled blocks. - #[arg( - long = "flashblocks.fixed", - default_value = "false", - env = "FLASHBLOCK_FIXED" - )] + #[arg(long = "flashblocks.fixed", default_value = "false", env = "FLASHBLOCK_FIXED")] pub flashblocks_fixed: bool, /// Time by which blocks would be completed earlier in milliseconds. /// /// This time used to account for latencies, this time would be deducted from total block /// building time before calculating number of fbs. - #[arg( - long = "flashblocks.leeway-time", - default_value = "75", - env = "FLASHBLOCK_LEEWAY_TIME" - )] + #[arg(long = "flashblocks.leeway-time", default_value = "75", env = "FLASHBLOCK_LEEWAY_TIME")] pub flashblocks_leeway_time: u64, /// Whether to disable state root calculation for each flashblock @@ -191,9 +163,7 @@ pub struct FlashblocksArgs { impl Default for FlashblocksArgs { fn default() -> Self { let args = crate::args::Cli::parse_from(["dummy", "node"]); - let Commands::Node(node_command) = args.command else { - unreachable!() - }; + let Commands::Node(node_command) = args.command else { unreachable!() }; node_command.ext.flashblocks } } @@ -209,27 +179,17 @@ pub struct FlashblocksP2pArgs { pub p2p_enabled: bool, /// Port for the flashblocks p2p node - #[arg( - long = "flashblocks.p2p_port", - env = "FLASHBLOCK_P2P_PORT", - default_value = "9009" - )] + #[arg(long = "flashblocks.p2p_port", env = "FLASHBLOCK_P2P_PORT", default_value = "9009")] pub p2p_port: u16, /// Path to the file containing a hex-encoded libp2p private key. /// If the file does not exist, a new key will be generated. - #[arg( - long = "flashblocks.p2p_private_key_file", - env = "FLASHBLOCK_P2P_PRIVATE_KEY_FILE" - )] + #[arg(long = "flashblocks.p2p_private_key_file", env = "FLASHBLOCK_P2P_PRIVATE_KEY_FILE")] pub p2p_private_key_file: Option, /// Comma-separated list of multiaddrs of known Flashblocks peers /// Example: "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ,/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ" - #[arg( - long = "flashblocks.p2p_known_peers", - env = "FLASHBLOCK_P2P_KNOWN_PEERS" - )] + #[arg(long = "flashblocks.p2p_known_peers", env = "FLASHBLOCK_P2P_KNOWN_PEERS")] pub p2p_known_peers: Option, /// Maximum number of peers for the flashblocks p2p node @@ -253,10 +213,6 @@ pub struct TelemetryArgs { pub otlp_headers: Option, /// Inverted sampling frequency in blocks. 1 - each block, 100 - every 100th block. - #[arg( - long = "telemetry.sampling-ratio", - env = "SAMPLING_RATIO", - default_value = "100" - )] + #[arg(long = "telemetry.sampling-ratio", env = "SAMPLING_RATIO", default_value = "100")] pub sampling_ratio: u64, } diff --git a/crates/builder/op-rbuilder/src/args/playground.rs b/crates/builder/op-rbuilder/src/args/playground.rs index 3ef24c1d..84e4f712 100644 --- a/crates/builder/op-rbuilder/src/args/playground.rs +++ b/crates/builder/op-rbuilder/src/args/playground.rs @@ -27,13 +27,19 @@ //! directory to use. This is useful for testing against different playground //! configurations. -use alloy_primitives::hex; -use clap::{CommandFactory, parser::ValueSource}; use core::{ net::{IpAddr, Ipv4Addr, SocketAddr}, ops::Range, time::Duration, }; +use std::{ + fs::read_to_string, + path::{Path, PathBuf}, + sync::Arc, +}; + +use alloy_primitives::hex; +use clap::{CommandFactory, parser::ValueSource}; use eyre::{Result, eyre}; use reth_cli::chainspec::ChainSpecParser; use reth_network_peers::TrustedPeer; @@ -41,11 +47,6 @@ use reth_optimism_chainspec::OpChainSpec; use reth_optimism_cli::{chainspec::OpChainSpecParser, commands::Commands}; use secp256k1::SecretKey; use serde_json::Value; -use std::{ - fs::read_to_string, - path::{Path, PathBuf}, - sync::Arc, -}; use url::{Host, Url}; use super::Cli; @@ -80,10 +81,7 @@ impl PlaygroundOptions { /// Creates a new `PlaygroundOptions` instance with the specified genesis path. pub(super) fn new(path: &Path) -> Result { if !path.exists() { - return Err(eyre!( - "Playground data directory {} does not exist", - path.display() - )); + return Err(eyre!("Playground data directory {} does not exist", path.display())); } let chain = OpChainSpecParser::parse(&existing_path(path, "l2-genesis.json")?)?; @@ -127,9 +125,8 @@ impl PlaygroundOptions { // either via the command line or an environment variable. Otherwise, don't // override the user provided values. let matches = Cli::command().get_matches(); - let matches = matches - .subcommand_matches("node") - .expect("validated that we are in the node command"); + let matches = + matches.subcommand_matches("node").expect("validated that we are in the node command"); if matches.value_source("chain").is_default() { node.chain = self.chain; @@ -223,9 +220,7 @@ fn extract_chain_block_time(basepath: &Path) -> Result { fn extract_deterministic_p2p_key(basepath: &Path) -> Result { let key = read_to_string(existing_path(basepath, "enode-key-1.txt")?)?; - Ok(SecretKey::from_slice( - &hex::decode(key).map_err(|e| eyre!("Invalid hex key: {e}"))?, - )?) + Ok(SecretKey::from_slice(&hex::decode(key).map_err(|e| eyre!("Invalid hex key: {e}"))?)?) } fn read_docker_compose(basepath: &Path) -> Result { @@ -238,9 +233,7 @@ fn extract_service_command_flag(basepath: &Path, service: &str, flag: &str) -> R let docker_compose = read_docker_compose(basepath)?; let args = docker_compose["services"][service]["command"] .as_sequence() - .ok_or(eyre!( - "docker-compose.yaml is missing command line arguments for {service}" - ))? + .ok_or(eyre!("docker-compose.yaml is missing command line arguments for {service}"))? .iter() .map(|s| { s.as_str().ok_or_else(|| { @@ -254,9 +247,8 @@ fn extract_service_command_flag(basepath: &Path, service: &str, flag: &str) -> R .position(|arg| *arg == flag) .ok_or_else(|| eyre!("docker_compose: {flag} not found on {service} service"))?; - let value = args - .get(index + 1) - .ok_or_else(|| eyre!("docker_compose: {flag} value not found"))?; + let value = + args.get(index + 1).ok_or_else(|| eyre!("docker_compose: {flag} value not found"))?; Ok(value.to_string()) } @@ -274,9 +266,7 @@ fn extract_trusted_peer_port(basepath: &Path) -> Result { // command line arguments used to start the op-geth service let Some(opgeth_args) = docker_compose["services"]["op-geth"]["command"][1].as_str() else { - return Err(eyre!( - "docker-compose.yaml is missing command line arguments for op-geth" - )); + return Err(eyre!("docker-compose.yaml is missing command line arguments for op-geth")); }; let opgeth_args = opgeth_args.split_whitespace().collect::>(); @@ -289,16 +279,12 @@ fn extract_trusted_peer_port(basepath: &Path) -> Result { .get(port_param_position + 1) .ok_or_else(|| eyre!("docker_compose: --port value not found"))?; - let port_value = port_value - .parse::() - .map_err(|e| eyre!("Invalid port value: {e}"))?; + let port_value = port_value.parse::().map_err(|e| eyre!("Invalid port value: {e}"))?; // now we need to find the external port of the op-geth service from the docker-compose.yaml // ports mapping used to start the op-geth service let Some(opgeth_ports) = docker_compose["services"]["op-geth"]["ports"].as_sequence() else { - return Err(eyre!( - "docker-compose.yaml is missing ports mapping for op-geth" - )); + return Err(eyre!("docker-compose.yaml is missing ports mapping for op-geth")); }; let ports_mapping = opgeth_ports .iter() diff --git a/crates/builder/op-rbuilder/src/bin/tester/main.rs b/crates/builder/op-rbuilder/src/bin/tester/main.rs index 52c4812e..11567d70 100644 --- a/crates/builder/op-rbuilder/src/bin/tester/main.rs +++ b/crates/builder/op-rbuilder/src/bin/tester/main.rs @@ -74,9 +74,7 @@ pub async fn run_system(validation: bool) -> eyre::Result<()> { let mut driver = ChainDriver::::remote(provider, engine_api); if validation { - driver = driver - .with_validation_node(ExternalNode::reth().await?) - .await?; + driver = driver.with_validation_node(ExternalNode::reth().await?).await?; } // Infinite loop generating blocks diff --git a/crates/builder/op-rbuilder/src/builders/builder_tx.rs b/crates/builder/op-rbuilder/src/builders/builder_tx.rs index 590ae1b2..3100ed23 100644 --- a/crates/builder/op-rbuilder/src/builders/builder_tx.rs +++ b/crates/builder/op-rbuilder/src/builders/builder_tx.rs @@ -1,3 +1,5 @@ +use core::fmt::Debug; + use alloy_consensus::TxEip1559; use alloy_eips::{Encodable2718, eip7623::TOTAL_COST_FLOOR_PER_TOKEN}; use alloy_evm::Database; @@ -7,7 +9,6 @@ use alloy_primitives::{ map::{HashMap, HashSet}, }; use alloy_sol_types::{ContractError, Revert, SolCall, SolError, SolInterface}; -use core::fmt::Debug; use op_alloy_consensus::OpTypedTransaction; use op_alloy_rpc_types::OpTransactionRequest; use op_revm::{OpHaltReason, OpTransactionError}; @@ -162,13 +163,7 @@ pub trait BuilderTransactions Result, BuilderTransactionError> { let mut simulation_state = self.new_simulation_state(state_provider.clone(), db); - self.simulate_builder_txs( - state_provider, - info, - ctx, - &mut simulation_state, - top_of_block, - ) + self.simulate_builder_txs(state_provider, info, ctx, &mut simulation_state, top_of_block) } fn add_builder_txs( @@ -188,9 +183,8 @@ pub trait BuilderTransactions res, Err(err) => { if err.is_invalid_tx_err() { - return Err(BuilderTransactionError::InvalidTransactionError(Box::new( - err, - ))); + return Err(BuilderTransactionError::InvalidTransactionError(Box::new(err))); } else { return Err(BuilderTransactionError::EvmExecutionError(Box::new(err))); } @@ -340,20 +331,10 @@ pub trait BuilderTransactions { - let topics: HashSet = logs - .into_iter() - .flat_map(|log| log.topics().to_vec()) - .collect(); - if !expected_logs - .iter() - .all(|expected_topic| topics.contains(expected_topic)) - { + ExecutionResult::Success { output, gas_used, logs, .. } => { + let topics: HashSet = + logs.into_iter().flat_map(|log| log.topics().to_vec()).collect(); + if !expected_logs.iter().all(|expected_topic| topics.contains(expected_topic)) { return Err(BuilderTransactionError::InvalidContract( to, InvalidContractDataError::InvalidLogs( @@ -398,10 +379,7 @@ pub(super) struct BuilderTxBase { impl BuilderTxBase { pub(super) fn new(signer: Option) -> Self { - Self { - signer, - _marker: std::marker::PhantomData, - } + Self { signer, _marker: std::marker::PhantomData } } pub(super) fn simulate_builder_tx( @@ -431,11 +409,7 @@ impl BuilderTxBase { fn estimate_builder_tx_gas(&self, input: &[u8]) -> u64 { // Count zero and non-zero bytes let (zero_bytes, nonzero_bytes) = input.iter().fold((0, 0), |(zeros, nonzeros), &byte| { - if byte == 0 { - (zeros + 1, nonzeros) - } else { - (zeros, nonzeros + 1) - } + if byte == 0 { (zeros + 1, nonzeros) } else { (zeros, nonzeros + 1) } }); // Calculate gas cost (4 gas per zero byte, 16 gas per non-zero byte) @@ -472,9 +446,7 @@ impl BuilderTxBase { ..Default::default() }); // Sign the transaction - let builder_tx = signer - .sign_tx(tx) - .map_err(BuilderTransactionError::SigningError)?; + let builder_tx = signer.sign_tx(tx).map_err(BuilderTransactionError::SigningError)?; Ok(builder_tx) } diff --git a/crates/builder/op-rbuilder/src/builders/context.rs b/crates/builder/op-rbuilder/src/builders/context.rs index 88dae9f3..44592085 100644 --- a/crates/builder/op-rbuilder/src/builders/context.rs +++ b/crates/builder/op-rbuilder/src/builders/context.rs @@ -1,10 +1,12 @@ +use core::fmt::Debug; +use std::{sync::Arc, time::Instant}; + use alloy_consensus::{Eip658Value, Transaction, conditional::BlockConditionalAttributes}; use alloy_eips::{Encodable2718, Typed2718}; use alloy_evm::Database; use alloy_op_evm::block::receipt_builder::OpReceiptBuilder; use alloy_primitives::{BlockHash, Bytes, U256}; use alloy_rpc_types_eth::Withdrawals; -use core::fmt::Debug; use op_alloy_consensus::OpDepositReceipt; use op_revm::OpSpecId; use reth_basic_payload_builder::PayloadConfig; @@ -35,7 +37,6 @@ use reth_primitives_traits::{InMemorySize, SignedTransaction}; use reth_revm::{State, context::Block}; use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction}; use revm::{DatabaseCommit, context::result::ResultAndState, interpreter::as_u64_saturated}; -use std::{sync::Arc, time::Instant}; use tokio_util::sync::CancellationToken; use tracing::{debug, info, trace}; @@ -122,10 +123,7 @@ impl OpPayloadBuilderCtx { pub fn block_gas_limit(&self) -> u64 { match self.gas_limit_config.gas_limit() { Some(gas_limit) => gas_limit, - None => self - .attributes() - .gas_limit - .unwrap_or(self.evm_env.block_env.gas_limit), + None => self.attributes().gas_limit.unwrap_or(self.evm_env.block_env.gas_limit), } } @@ -141,10 +139,7 @@ impl OpPayloadBuilderCtx { /// Returns the current blob gas price. pub fn get_blob_gasprice(&self) -> Option { - self.evm_env - .block_env - .blob_gasprice() - .map(|gasprice| gasprice as u64) + self.evm_env.block_env.blob_gasprice().map(|gasprice| gasprice as u64) } /// Returns the blob fields for the header. @@ -157,9 +152,8 @@ impl OpPayloadBuilderCtx { info: &ExecutionInfo, ) -> (Option, Option) { if self.is_jovian_active() { - let scalar = info - .da_footprint_scalar - .expect("Scalar must be defined for Jovian blocks"); + let scalar = + info.da_footprint_scalar.expect("Scalar must be defined for Jovian blocks"); let result = info.cumulative_da_bytes_used * scalar as u64; (Some(0), Some(result)) } else if self.is_ecotone_active() { @@ -206,38 +200,32 @@ impl OpPayloadBuilderCtx { /// Returns true if regolith is active for the payload. pub fn is_regolith_active(&self) -> bool { - self.chain_spec - .is_regolith_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_regolith_active_at_timestamp(self.attributes().timestamp()) } /// Returns true if ecotone is active for the payload. pub fn is_ecotone_active(&self) -> bool { - self.chain_spec - .is_ecotone_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_ecotone_active_at_timestamp(self.attributes().timestamp()) } /// Returns true if canyon is active for the payload. pub fn is_canyon_active(&self) -> bool { - self.chain_spec - .is_canyon_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_canyon_active_at_timestamp(self.attributes().timestamp()) } /// Returns true if holocene is active for the payload. pub fn is_holocene_active(&self) -> bool { - self.chain_spec - .is_holocene_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_holocene_active_at_timestamp(self.attributes().timestamp()) } /// Returns true if isthmus is active for the payload. pub fn is_isthmus_active(&self) -> bool { - self.chain_spec - .is_isthmus_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_isthmus_active_at_timestamp(self.attributes().timestamp()) } /// Returns true if isthmus is active for the payload. pub fn is_jovian_active(&self) -> bool { - self.chain_spec - .is_jovian_active_at_timestamp(self.attributes().timestamp()) + self.chain_spec.is_jovian_active_at_timestamp(self.attributes().timestamp()) } /// Returns the chain id @@ -300,12 +288,9 @@ impl OpPayloadBuilderCtx { // purely for the purposes of utilizing the `evm_config.tx_env`` function. // Deposit transactions do not have signatures, so if the tx is a deposit, this // will just pull in its `from` address. - let sequencer_tx = sequencer_tx - .value() - .try_clone_into_recovered() - .map_err(|_| { - PayloadBuilderError::other(OpPayloadBuilderError::TransactionEcRecoverFailed) - })?; + let sequencer_tx = sequencer_tx.value().try_clone_into_recovered().map_err(|_| { + PayloadBuilderError::other(OpPayloadBuilderError::TransactionEcRecoverFailed) + })?; // Cache the depositor account prior to the state transition for the deposit nonce. // @@ -445,10 +430,8 @@ impl OpPayloadBuilderCtx { num_txs_considered += 1; - let TxData { - metering: _resource_usage, - backrun_bundles, - } = self.tx_data_store.get(&tx_hash); + let TxData { metering: _resource_usage, backrun_bundles } = + self.tx_data_store.get(&tx_hash); // TODO: ideally we should get this from the txpool stream if let Some(conditional) = conditional @@ -526,9 +509,7 @@ impl OpPayloadBuilderCtx { } }; - self.metrics - .tx_simulation_duration - .record(tx_simulation_start_time.elapsed()); + self.metrics.tx_simulation_duration.record(tx_simulation_start_time.elapsed()); self.metrics.tx_byte_size.record(tx.inner().size() as f64); num_txs_simulated += 1; @@ -536,11 +517,7 @@ impl OpPayloadBuilderCtx { // reverted or not, as this is a check against maliciously searchers // sending txs that are expensive to compute but always revert. let gas_used = result.gas_used(); - if self - .address_gas_limiter - .consume_gas(tx.signer(), gas_used) - .is_err() - { + if self.address_gas_limiter.consume_gas(tx.signer(), gas_used).is_err() { log_txn(TxnExecutionResult::MaxGasUsageExceeded); best_txs.mark_invalid(tx.signer(), tx.nonce()); continue; @@ -625,9 +602,7 @@ impl OpPayloadBuilderCtx { .map(|tx| tx.effective_tip_per_gas(base_fee).unwrap_or(0)) .sum(); if total_effective_tip < miner_fee { - self.metrics - .backrun_bundles_rejected_low_fee_total - .increment(1); + self.metrics.backrun_bundles_rejected_low_fee_total.increment(1); info!( target: "payload_builder", bundle_id = ?stored_bundle.bundle_id, @@ -638,16 +613,10 @@ impl OpPayloadBuilderCtx { break 'bundle_loop; } - let total_backrun_gas: u64 = stored_bundle - .backrun_txs - .iter() - .map(|tx| tx.gas_limit()) - .sum(); - let total_backrun_da_size: u64 = stored_bundle - .backrun_txs - .iter() - .map(|tx| tx.estimated_da_size()) - .sum(); + let total_backrun_gas: u64 = + stored_bundle.backrun_txs.iter().map(|tx| tx.gas_limit()).sum(); + let total_backrun_da_size: u64 = + stored_bundle.backrun_txs.iter().map(|tx| tx.estimated_da_size()).sum(); if let Err(result) = info.is_tx_over_limits( total_backrun_da_size, @@ -658,9 +627,7 @@ impl OpPayloadBuilderCtx { info.da_footprint_scalar, block_da_footprint_limit, ) { - self.metrics - .backrun_bundles_rejected_over_limits_total - .increment(1); + self.metrics.backrun_bundles_rejected_over_limits_total.increment(1); info!( target: "payload_builder", bundle_id = ?stored_bundle.bundle_id, @@ -740,9 +707,7 @@ impl OpPayloadBuilderCtx { self.metrics.backrun_bundles_landed_total.increment(1); } - self.metrics - .backrun_bundle_execution_duration - .record(backrun_start_time.elapsed()); + self.metrics.backrun_bundle_execution_duration.record(backrun_start_time.elapsed()); // Remove the target tx from the backrun bundle store as already executed self.tx_data_store.remove_backrun_bundles(&tx_hash); diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/best_txs.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/best_txs.rs index ec2a45d1..6e612fce 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/best_txs.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/best_txs.rs @@ -1,7 +1,8 @@ +use std::{collections::HashSet, sync::Arc}; + use alloy_primitives::{Address, TxHash}; use reth_payload_util::PayloadTransactions; use reth_transaction_pool::{PoolTransaction, ValidPoolTransaction}; -use std::{collections::HashSet, sync::Arc}; use tracing::debug; use crate::tx::MaybeFlashblockFilter; @@ -24,11 +25,7 @@ where I: Iterator>>, { pub(super) fn new(inner: reth_payload_util::BestPayloadTransactions) -> Self { - Self { - inner, - current_flashblock_number: 0, - commited_transactions: Default::default(), - } + Self { inner, current_flashblock_number: 0, commited_transactions: Default::default() } } /// Replaces current iterator with new one. We use it on new flashblock building, to refresh @@ -102,14 +99,16 @@ where #[cfg(test)] mod tests { + use std::sync::Arc; + + use alloy_consensus::Transaction; + use reth_payload_util::{BestPayloadTransactions, PayloadTransactions}; + use reth_transaction_pool::{CoinbaseTipOrdering, PoolTransaction, pool::PendingPool}; + use crate::{ builders::flashblocks::best_txs::BestFlashblocksTxs, mock_tx::{MockFbTransaction, MockFbTransactionFactory}, }; - use alloy_consensus::Transaction; - use reth_payload_util::{BestPayloadTransactions, PayloadTransactions}; - use reth_transaction_pool::{CoinbaseTipOrdering, PoolTransaction, pool::PendingPool}; - use std::sync::Arc; #[test] fn test_simple_case() { diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/builder_tx.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/builder_tx.rs index bc1063ac..ed5cd1bb 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/builder_tx.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/builder_tx.rs @@ -1,10 +1,11 @@ +use core::fmt::Debug; + use alloy_eips::Encodable2718; use alloy_evm::{Database, Evm}; use alloy_op_evm::OpEvm; use alloy_primitives::{Address, B256, Signature, U256}; use alloy_rpc_types_eth::TransactionInput; use alloy_sol_types::{SolCall, SolEvent, sol}; -use core::fmt::Debug; use op_alloy_rpc_types::OpTransactionRequest; use reth_evm::{ConfigureEvm, precompiles::PrecompilesMap}; use reth_provider::StateProvider; @@ -70,10 +71,7 @@ impl FlashblocksBuilderTx { >, ) -> Self { let base_builder_tx = BuilderTxBase::new(signer); - Self { - base_builder_tx, - flashtestations_builder_tx, - } + Self { base_builder_tx, flashtestations_builder_tx } } } @@ -222,12 +220,7 @@ impl FlashblocksNumberBuilderTx { )?; let da_size = op_alloy_flz::tx_estimated_size_fjord_bytes(signed_tx.encoded_2718().as_slice()); - Ok(BuilderTransactionCtx { - signed_tx, - gas_used, - da_size, - is_top_of_block: true, - }) + Ok(BuilderTransactionCtx { signed_tx, gas_used, da_size, is_top_of_block: true }) } fn simulate_flashblocks_readonly_call( diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/config.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/config.rs index cdc6ae91..8aa4b56a 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/config.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/config.rs @@ -1,11 +1,12 @@ -use alloy_primitives::Address; - -use crate::{args::OpRbuilderArgs, builders::BuilderConfig}; use core::{ net::{Ipv4Addr, SocketAddr}, time::Duration, }; +use alloy_primitives::Address; + +use crate::{args::OpRbuilderArgs, builders::BuilderConfig}; + /// Configuration values that are specific to the flashblocks builder. #[derive(Debug, Clone)] pub struct FlashblocksConfig { diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/ctx.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/ctx.rs index 5f7f46cb..3d9dd38b 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/ctx.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/ctx.rs @@ -1,10 +1,5 @@ -use crate::{ - builders::{BuilderConfig, OpPayloadBuilderCtx, flashblocks::FlashblocksConfig}, - gas_limiter::{AddressGasLimiter, args::GasLimiterArgs}, - metrics::OpRBuilderMetrics, - traits::ClientBounds, - tx_data_store::TxDataStore, -}; +use std::sync::Arc; + use op_revm::OpSpecId; use reth_basic_payload_builder::PayloadConfig; use reth_evm::EvmEnv; @@ -15,9 +10,16 @@ use reth_optimism_payload_builder::{ config::{OpDAConfig, OpGasLimitConfig}, }; use reth_optimism_primitives::OpTransactionSigned; -use std::sync::Arc; use tokio_util::sync::CancellationToken; +use crate::{ + builders::{BuilderConfig, OpPayloadBuilderCtx, flashblocks::FlashblocksConfig}, + gas_limiter::{AddressGasLimiter, args::GasLimiterArgs}, + metrics::OpRBuilderMetrics, + traits::ClientBounds, + tx_data_store::TxDataStore, +}; + #[derive(Debug, Clone)] pub(super) struct OpPayloadSyncerCtx { /// The type that knows how to perform system calls and configure the evm. diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/mod.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/mod.rs index 87d4494c..14fb3a46 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/mod.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/mod.rs @@ -1,8 +1,9 @@ -use super::BuilderConfig; -use crate::traits::{NodeBounds, PoolBounds}; use config::FlashblocksConfig; use service::FlashblocksServiceBuilder; +use super::BuilderConfig; +use crate::traits::{NodeBounds, PoolBounds}; + mod best_txs; mod builder_tx; mod config; diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/p2p.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/p2p.rs index 23229923..38352289 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/p2p.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/p2p.rs @@ -52,10 +52,6 @@ impl From for RethOpBuiltPayload { impl From for OpBuiltPayload { fn from(value: RethOpBuiltPayload) -> Self { - OpBuiltPayload { - id: value.id(), - block: value.block().clone(), - fees: value.fees(), - } + OpBuiltPayload { id: value.id(), block: value.block().clone(), fees: value.fees() } } } diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/payload.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/payload.rs index cdcfe952..7461cece 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/payload.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/payload.rs @@ -1,23 +1,18 @@ -use super::{config::FlashblocksConfig, wspub::WebSocketPublisher}; -use crate::{ - builders::{ - BuilderConfig, - builder_tx::BuilderTransactions, - context::OpPayloadBuilderCtx, - flashblocks::{best_txs::BestFlashblocksTxs, config::FlashBlocksConfigExt}, - generator::{BlockCell, BuildArguments, PayloadBuilder}, - }, - gas_limiter::AddressGasLimiter, - metrics::OpRBuilderMetrics, - primitives::reth::ExecutionInfo, - traits::{ClientBounds, PoolBounds}, +use core::time::Duration; +use std::{ + ops::{Div, Rem}, + sync::Arc, + time::Instant, }; + use alloy_consensus::{ BlockBody, EMPTY_OMMER_ROOT_HASH, Header, constants::EMPTY_WITHDRAWALS, proofs, }; use alloy_eips::{Encodable2718, eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; use alloy_primitives::{Address, B256, U256, map::foldhash::HashMap}; -use core::time::Duration; +use base_flashtypes::{ + ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1, FlashblocksPayloadV1, +}; use eyre::WrapErr as _; use reth_basic_payload_builder::BuildOutcome; use reth_chain_state::ExecutedBlock; @@ -33,7 +28,8 @@ use reth_payload_primitives::PayloadBuilderAttributes; use reth_payload_util::BestPayloadTransactions; use reth_primitives_traits::RecoveredBlock; use reth_provider::{ - ExecutionOutcome, HashedPostStateProvider, ProviderError, StateProvider, StateRootProvider, StorageRootProvider + ExecutionOutcome, HashedPostStateProvider, ProviderError, StateProvider, StateRootProvider, + StorageRootProvider, }; use reth_revm::{ State, database::StateProviderDatabase, db::states::bundle_state::BundleRetention, @@ -42,15 +38,24 @@ use reth_transaction_pool::TransactionPool; use reth_trie::{HashedPostState, updates::TrieUpdates}; use revm::Database; use serde::{Deserialize, Serialize}; -use std::{ - ops::{Div, Rem}, - sync::Arc, - time::Instant, -}; use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info, metadata::Level, span, warn}; -use base_flashtypes::{FlashblocksPayloadV1, ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1}; + +use super::{config::FlashblocksConfig, wspub::WebSocketPublisher}; +use crate::{ + builders::{ + BuilderConfig, + builder_tx::BuilderTransactions, + context::OpPayloadBuilderCtx, + flashblocks::{best_txs::BestFlashblocksTxs, config::FlashBlocksConfigExt}, + generator::{BlockCell, BuildArguments, PayloadBuilder}, + }, + gas_limiter::AddressGasLimiter, + metrics::OpRBuilderMetrics, + primitives::reth::ExecutionInfo, + traits::{ClientBounds, PoolBounds}, +}; type NextBestFlashblocksTxs = BestFlashblocksTxs< ::Transaction, @@ -248,14 +253,8 @@ where 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, + 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, }; @@ -297,28 +296,18 @@ where best_payload: BlockCell, ) -> Result<(), PayloadBuilderError> { let block_build_start_time = Instant::now(); - let BuildArguments { - mut cached_reads, - config, - cancel: block_cancel, - } = args; + let BuildArguments { mut cached_reads, config, cancel: block_cancel } = args; // We log only every 100th block to reduce usage let span = if cfg!(feature = "telemetry") - && config - .parent_header - .number - .is_multiple_of(self.config.sampling_ratio) + && config.parent_header.number.is_multiple_of(self.config.sampling_ratio) { span!(Level::INFO, "build_payload") } else { tracing::Span::none() }; let _entered = span.enter(); - span.record( - "payload_id", - config.attributes.payload_attributes.id.to_string(), - ); + span.record("payload_id", config.attributes.payload_attributes.id.to_string()); let timestamp = config.attributes.timestamp(); let disable_state_root = self.config.specific.disable_state_root; @@ -340,10 +329,8 @@ where // 1. execute the pre steps and seal an early block with that let sequencer_tx_start_time = Instant::now(); - let mut state = State::builder() - .with_database(cached_reads.as_db_mut(db)) - .with_bundle_update() - .build(); + let mut state = + State::builder().with_database(cached_reads.as_db_mut(db)).with_bundle_update().build(); let mut info = execute_pre_steps(&mut state, &ctx)?; let sequencer_tx_time = sequencer_tx_start_time.elapsed(); @@ -353,8 +340,7 @@ where // We add first builder tx right after deposits if !ctx.attributes().no_tx_pool && let Err(e) = - self.builder_tx - .add_builder_txs(&state_provider, &mut info, &ctx, &mut state, false) + self.builder_tx.add_builder_txs(&state_provider, &mut info, &ctx, &mut state, false) { error!( target: "payload_builder", @@ -370,10 +356,7 @@ where !disable_state_root || ctx.attributes().no_tx_pool, // need to calculate state root for CL sync )?; - self.payload_tx - .send(payload.clone()) - .await - .map_err(PayloadBuilderError::other)?; + self.payload_tx.send(payload.clone()).await.map_err(PayloadBuilderError::other)?; best_payload.set(payload); info!( @@ -384,13 +367,9 @@ where // not emitting flashblock if no_tx_pool in FCU, it's just syncing if !ctx.attributes().no_tx_pool { - let flashblock_byte_size = self - .ws_pub - .publish(&fb_payload) - .map_err(PayloadBuilderError::other)?; - ctx.metrics - .flashblock_byte_size_histogram - .record(flashblock_byte_size as f64); + let flashblock_byte_size = + self.ws_pub.publish(&fb_payload).map_err(PayloadBuilderError::other)?; + ctx.metrics.flashblock_byte_size_histogram.record(flashblock_byte_size as f64); } if ctx.attributes().no_tx_pool { @@ -400,18 +379,10 @@ where ); let total_block_building_time = block_build_start_time.elapsed(); - ctx.metrics - .total_block_built_duration - .record(total_block_building_time); - ctx.metrics - .total_block_built_gauge - .set(total_block_building_time); - ctx.metrics - .payload_num_tx - .record(info.executed_transactions.len() as f64); - ctx.metrics - .payload_num_tx_gauge - .set(info.executed_transactions.len() as f64); + ctx.metrics.total_block_built_duration.record(total_block_building_time); + ctx.metrics.total_block_built_gauge.set(total_block_building_time); + ctx.metrics.payload_num_tx.record(info.executed_transactions.len() as f64); + ctx.metrics.payload_num_tx_gauge.set(info.executed_transactions.len() as f64); // return early since we don't need to build a block with transactions from the pool return Ok(()); @@ -427,18 +398,13 @@ where flashblocks_interval = self.config.specific.interval.as_millis(), ); ctx.metrics.reduced_flashblocks_number.record( - self.config - .flashblocks_per_block() - .saturating_sub(ctx.target_flashblock_count()) as f64, + self.config.flashblocks_per_block().saturating_sub(ctx.target_flashblock_count()) + as f64, ); - ctx.metrics - .first_flashblock_time_offset - .record(first_flashblock_offset.as_millis() as f64); + ctx.metrics.first_flashblock_time_offset.record(first_flashblock_offset.as_millis() as f64); let gas_per_batch = ctx.block_gas_limit() / flashblocks_per_block; - let da_per_batch = ctx - .da_config - .max_da_block_size() - .map(|da_limit| da_limit / flashblocks_per_block); + let da_per_batch = + ctx.da_config.max_da_block_size().map(|da_limit| da_limit / flashblocks_per_block); // Check that builder tx won't affect fb limit too much if let Some(da_limit) = da_per_batch { // We error if we can't insert any tx aside from builder tx in flashblock @@ -448,9 +414,8 @@ where ); } } - let da_footprint_per_batch = info - .da_footprint_scalar - .map(|_| ctx.block_gas_limit() / flashblocks_per_block); + let da_footprint_per_batch = + info.da_footprint_scalar.map(|_| ctx.block_gas_limit() / flashblocks_per_block); let extra_ctx = FlashblocksExtraCtx { flashblock_index: 1, @@ -471,8 +436,7 @@ where // Create best_transaction iterator let mut best_txs = BestFlashblocksTxs::new(BestPayloadTransactions::new( - self.pool - .best_transactions_with_attributes(ctx.best_transaction_attributes()), + self.pool.best_transactions_with_attributes(ctx.best_transaction_attributes()), )); let interval = self.config.specific.interval; let (tx, mut rx) = mpsc::channel((self.config.flashblocks_per_block() + 1) as usize); @@ -626,10 +590,7 @@ where let flashblock_build_start_time = Instant::now(); let builder_txs = - match self - .builder_tx - .add_builder_txs(&state_provider, info, ctx, state, true) - { + match self.builder_tx.add_builder_txs(&state_provider, info, ctx, state, true) { Ok(builder_txs) => builder_txs, Err(e) => { error!(target: "payload_builder", "Error simulating builder txs: {}", e); @@ -643,10 +604,8 @@ where .iter() .filter(|tx| !tx.is_top_of_block) .fold(0, |acc, tx| acc + tx.gas_used); - let builder_tx_da_size: u64 = builder_txs - .iter() - .filter(|tx| !tx.is_top_of_block) - .fold(0, |acc, tx| acc + tx.da_size); + let builder_tx_da_size: u64 = + builder_txs.iter().filter(|tx| !tx.is_top_of_block).fold(0, |acc, tx| acc + tx.da_size); target_gas_for_batch = target_gas_for_batch.saturating_sub(builder_tx_gas); // saturating sub just in case, we will log an error if da_limit too small for builder_tx_da_size @@ -654,28 +613,22 @@ where *da_limit = da_limit.saturating_sub(builder_tx_da_size); } - if let (Some(footprint), Some(scalar)) = ( - target_da_footprint_for_batch.as_mut(), - info.da_footprint_scalar, - ) { + if let (Some(footprint), Some(scalar)) = + (target_da_footprint_for_batch.as_mut(), info.da_footprint_scalar) + { *footprint = footprint.saturating_sub(builder_tx_da_size.saturating_mul(scalar as u64)); } let best_txs_start_time = Instant::now(); best_txs.refresh_iterator( BestPayloadTransactions::new( - self.pool - .best_transactions_with_attributes(ctx.best_transaction_attributes()), + self.pool.best_transactions_with_attributes(ctx.best_transaction_attributes()), ), flashblock_index, ); let transaction_pool_fetch_time = best_txs_start_time.elapsed(); - ctx.metrics - .transaction_pool_fetch_duration - .record(transaction_pool_fetch_time); - ctx.metrics - .transaction_pool_fetch_gauge - .set(transaction_pool_fetch_time); + ctx.metrics.transaction_pool_fetch_duration.record(transaction_pool_fetch_time); + ctx.metrics.transaction_pool_fetch_gauge.set(transaction_pool_fetch_time); let tx_execution_start_time = Instant::now(); ctx.execute_best_transactions( @@ -712,14 +665,9 @@ where ctx.metrics .payload_transaction_simulation_duration .record(payload_transaction_simulation_time); - ctx.metrics - .payload_transaction_simulation_gauge - .set(payload_transaction_simulation_time); + ctx.metrics.payload_transaction_simulation_gauge.set(payload_transaction_simulation_time); - if let Err(e) = self - .builder_tx - .add_builder_txs(&state_provider, info, ctx, state, false) - { + if let Err(e) = self.builder_tx.add_builder_txs(&state_provider, info, ctx, state, false) { error!(target: "payload_builder", "Error simulating builder txs: {}", e); }; @@ -731,12 +679,8 @@ where !ctx.extra_ctx.disable_state_root || ctx.attributes().no_tx_pool, ); let total_block_built_duration = total_block_built_duration.elapsed(); - ctx.metrics - .total_block_built_duration - .record(total_block_built_duration); - ctx.metrics - .total_block_built_gauge - .set(total_block_built_duration); + ctx.metrics.total_block_built_duration.record(total_block_built_duration); + ctx.metrics.total_block_built_gauge.set(total_block_built_duration); match build_result { Err(err) => { @@ -770,12 +714,8 @@ where best_payload.set(new_payload); // Record flashblock build duration - ctx.metrics - .flashblock_build_duration - .record(flashblock_build_start_time.elapsed()); - ctx.metrics - .flashblock_byte_size_histogram - .record(flashblock_byte_size as f64); + ctx.metrics.flashblock_build_duration.record(flashblock_build_start_time.elapsed()); + ctx.metrics.flashblock_byte_size_histogram.record(flashblock_byte_size as f64); ctx.metrics .flashblock_num_tx_histogram .record(info.executed_transactions.len() as f64); @@ -794,10 +734,9 @@ where let target_gas_for_batch = ctx.extra_ctx.target_gas_for_batch + ctx.extra_ctx.gas_per_batch; - if let (Some(footprint), Some(da_footprint_limit)) = ( - target_da_footprint_for_batch.as_mut(), - ctx.extra_ctx.da_footprint_per_batch, - ) { + if let (Some(footprint), Some(da_footprint_limit)) = + (target_da_footprint_for_batch.as_mut(), ctx.extra_ctx.da_footprint_per_batch) + { *footprint += da_footprint_limit; } @@ -831,18 +770,12 @@ where message: &str, ) { ctx.metrics.block_built_success.increment(1); - ctx.metrics - .flashblock_count - .record(ctx.flashblock_index() as f64); + ctx.metrics.flashblock_count.record(ctx.flashblock_index() as f64); ctx.metrics .missing_flashblocks_count .record(flashblocks_per_block.saturating_sub(ctx.flashblock_index()) as f64); - ctx.metrics - .payload_num_tx - .record(info.executed_transactions.len() as f64); - ctx.metrics - .payload_num_tx_gauge - .set(info.executed_transactions.len() as f64); + ctx.metrics.payload_num_tx.record(info.executed_transactions.len() as f64); + ctx.metrics.payload_num_tx_gauge.set(info.executed_transactions.len() as f64); debug!( target: "payload_builder", @@ -881,16 +814,10 @@ where ?target_time, ?now, ); - return ( - self.config.flashblocks_per_block(), - self.config.specific.interval, - ); + return (self.config.flashblocks_per_block(), self.config.specific.interval); }; self.metrics.flashblocks_time_drift.record( - self.config - .block_time - .as_millis() - .saturating_sub(time_drift.as_millis()) as f64, + self.config.block_time.as_millis().saturating_sub(time_drift.as_millis()) as f64, ); debug!( target: "payload_builder", @@ -909,10 +836,7 @@ where (time_drift.div(interval), Duration::from_millis(interval)) } else { // Non-perfect division, so we account for it. - ( - time_drift.div(interval) + 1, - Duration::from_millis(first_flashblock_offset), - ) + (time_drift.div(interval) + 1, Duration::from_millis(first_flashblock_offset)) } } } @@ -980,12 +904,8 @@ where let state_merge_start_time = Instant::now(); state.merge_transitions(BundleRetention::Reverts); let state_transition_merge_time = state_merge_start_time.elapsed(); - ctx.metrics - .state_transition_merge_duration - .record(state_transition_merge_time); - ctx.metrics - .state_transition_merge_gauge - .set(state_transition_merge_time); + ctx.metrics.state_transition_merge_duration.record(state_transition_merge_time); + ctx.metrics.state_transition_merge_gauge.set(state_transition_merge_time); let block_number = ctx.block_number(); assert_eq!(block_number, ctx.parent().number + 1); @@ -1006,9 +926,7 @@ where ) }) .expect("Number is in range"); - let logs_bloom = execution_outcome - .block_logs_bloom(block_number) - .expect("Number is in range"); + let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); // TODO: maybe recreate state with bundle in here // calculate the state root @@ -1021,49 +939,38 @@ where let state_provider = state.database.as_ref(); hashed_state = state_provider.hashed_post_state(execution_outcome.state()); (state_root, trie_output) = { - state - .database - .as_ref() - .state_root_with_updates(hashed_state.clone()) - .inspect_err(|err| { + 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" ); - })? + }, + )? }; let state_root_calculation_time = state_root_start_time.elapsed(); - ctx.metrics - .state_root_calculation_duration - .record(state_root_calculation_time); - ctx.metrics - .state_root_calculation_gauge - .set(state_root_calculation_time); + ctx.metrics.state_root_calculation_duration.record(state_root_calculation_time); + ctx.metrics.state_root_calculation_gauge.set(state_root_calculation_time); } let mut requests_hash = None; - let withdrawals_root = if ctx - .chain_spec - .is_isthmus_active_at_timestamp(ctx.attributes().timestamp()) - { - // always empty requests hash post isthmus - requests_hash = Some(EMPTY_REQUESTS_HASH); - - // 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)?, - ) - } else if ctx - .chain_spec - .is_canyon_active_at_timestamp(ctx.attributes().timestamp()) - { - Some(EMPTY_WITHDRAWALS) - } else { - None - }; + let withdrawals_root = + if ctx.chain_spec.is_isthmus_active_at_timestamp(ctx.attributes().timestamp()) { + // always empty requests hash post isthmus + requests_hash = Some(EMPTY_REQUESTS_HASH); + + // 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)?, + ) + } else if ctx.chain_spec.is_canyon_active_at_timestamp(ctx.attributes().timestamp()) { + Some(EMPTY_WITHDRAWALS) + } else { + None + }; // create the block header let transactions_root = proofs::calculate_transaction_root(&info.executed_transactions); @@ -1125,11 +1032,8 @@ where // pick the new transactions from the info field and update the last flashblock index let new_transactions = info.executed_transactions[info.extra.last_flashblock_index..].to_vec(); - let new_transactions_encoded = new_transactions - .clone() - .into_iter() - .map(|tx| tx.encoded_2718().into()) - .collect::>(); + let new_transactions_encoded = + new_transactions.clone().into_iter().map(|tx| tx.encoded_2718().into()).collect::>(); let new_receipts = info.receipts[info.extra.last_flashblock_index..].to_vec(); info.extra.last_flashblock_index = info.executed_transactions.len(); @@ -1191,12 +1095,7 @@ where state.transition_state = untouched_transition_state; Ok(( - OpBuiltPayload::new( - ctx.payload_id(), - sealed_block, - info.total_fees, - Some(executed), - ), + OpBuiltPayload::new(ctx.payload_id(), sealed_block, info.total_fees, Some(executed)), fb_payload, )) } diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/payload_handler.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/payload_handler.rs index 70f1be66..ef566087 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/payload_handler.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/payload_handler.rs @@ -1,10 +1,5 @@ -use crate::{ - builders::flashblocks::{ - ctx::OpPayloadSyncerCtx, p2p::Message, payload::FlashblocksExecutionInfo, - }, - primitives::reth::ExecutionInfo, - traits::ClientBounds, -}; +use std::sync::Arc; + use alloy_evm::eth::receipt_builder::ReceiptBuilderCtx; use alloy_primitives::B64; use base_flashtypes::FlashblocksPayloadV1; @@ -21,10 +16,17 @@ use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; use reth_payload_builder::EthPayloadBuilderAttributes; use reth_primitives::SealedHeader; use reth_revm::{State, cached::CachedReads, database::StateProviderDatabase}; -use std::sync::Arc; use tokio::sync::mpsc; use tracing::warn; +use crate::{ + builders::flashblocks::{ + ctx::OpPayloadSyncerCtx, p2p::Message, payload::FlashblocksExecutionInfo, + }, + primitives::reth::ExecutionInfo, + traits::ClientBounds, +}; + /// Handles newly built or received flashblock payloads. /// /// In the case of a payload built by this node, it is broadcast to peers and an event is sent to the payload builder. @@ -59,27 +61,12 @@ where client: Client, cancel: tokio_util::sync::CancellationToken, ) -> Self { - Self { - built_rx, - p2p_rx, - p2p_tx, - payload_events_handle, - ctx, - client, - cancel, - } + Self { built_rx, p2p_rx, p2p_tx, payload_events_handle, ctx, client, cancel } } pub(crate) async fn run(self) { - let Self { - mut built_rx, - mut p2p_rx, - p2p_tx, - payload_events_handle, - ctx, - client, - cancel, - } = self; + let Self { mut built_rx, mut p2p_rx, p2p_tx, payload_events_handle, ctx, client, cancel } = + self; tracing::debug!("flashblocks payload handler started"); @@ -154,14 +141,11 @@ where .wrap_err("failed to get parent header")? .ok_or_else(|| eyre::eyre!("parent header not found"))?; - let state_provider = client - .state_by_block_hash(parent_hash) - .wrap_err("failed to get state for parent hash")?; + let state_provider = + client.state_by_block_hash(parent_hash).wrap_err("failed to get state for parent hash")?; let db = StateProviderDatabase::new(&state_provider); - let mut state = State::builder() - .with_database(cached_reads.as_db_mut(db)) - .with_bundle_update() - .build(); + let mut state = + State::builder().with_database(cached_reads.as_db_mut(db)).with_bundle_update().build(); let chain_spec = client.chain_spec(); let timestamp = payload.block().header().timestamp(); @@ -207,12 +191,7 @@ where id: payload.id(), // unused parent: parent_hash, // unused suggested_fee_recipient: payload.block().sealed_header().beneficiary, - withdrawals: payload - .block() - .body() - .withdrawals - .clone() - .unwrap_or_default(), + withdrawals: payload.block().body().withdrawals.clone().unwrap_or_default(), parent_beacon_block_root: payload.block().sealed_header().parent_beacon_block_root, timestamp, prev_randao: payload.block().sealed_header().mix_hash, @@ -249,10 +228,7 @@ where ) .wrap_err("failed to build flashblock")?; - builder_ctx - .metrics - .flashblock_sync_duration - .record(start.elapsed()); + builder_ctx.metrics.flashblock_sync_duration.record(start.elapsed()); if built_payload.block().hash() != payload.block().hash() { tracing::error!( @@ -294,9 +270,7 @@ fn execute_transactions( let mut evm = evm_config.evm_with_env(&mut *state, evm_env); for tx in txs { - let sender = tx - .recover_signer() - .wrap_err("failed to recover tx signer")?; + let sender = tx.recover_signer().wrap_err("failed to recover tx signer")?; let tx_env = TxEnv::from_recovered_tx(&tx, sender); let executable_tx = match tx { OpTxEnvelope::Deposit(ref tx) => { @@ -305,11 +279,7 @@ fn execute_transactions( source_hash: tx.source_hash, is_system_transaction: tx.is_system_transaction, }; - OpTransaction { - base: tx_env, - enveloped_tx: None, - deposit, - } + OpTransaction { base: tx_env, enveloped_tx: None, deposit } } OpTxEnvelope::Legacy(_) => { let mut tx = OpTransaction::new(tx_env); @@ -349,16 +319,12 @@ fn execute_transactions( if let Some(max_gas_per_txn) = max_gas_per_txn && result.gas_used() > max_gas_per_txn { - return Err(eyre::eyre!( - "transaction exceeded max gas per txn limit in flashblock" - )); + return Err(eyre::eyre!("transaction exceeded max gas per txn limit in flashblock")); } let tx_gas_used = result.gas_used(); - info.cumulative_gas_used = info - .cumulative_gas_used - .checked_add(tx_gas_used) - .ok_or_else(|| { + info.cumulative_gas_used = + info.cumulative_gas_used.checked_add(tx_gas_used).ok_or_else(|| { eyre::eyre!("total gas used overflowed when executing flashblock transactions") })?; if info.cumulative_gas_used > gas_limit { @@ -382,12 +348,7 @@ fn execute_transactions( cumulative_gas_used: info.cumulative_gas_used, }; - info.receipts.push(build_receipt( - evm_config, - ctx, - depositor_nonce, - is_canyon_active, - )); + info.receipts.push(build_receipt(evm_config, ctx, depositor_nonce, is_canyon_active)); evm.db_mut().commit(state); diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/service.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/service.rs index 2c1e684b..f88658d2 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/service.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/service.rs @@ -1,3 +1,13 @@ +use std::sync::Arc; + +use eyre::WrapErr as _; +use reth_basic_payload_builder::BasicPayloadJobGeneratorConfig; +use reth_node_api::NodeTypes; +use reth_node_builder::{BuilderContext, components::PayloadServiceBuilder}; +use reth_optimism_evm::OpEvmConfig; +use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; +use reth_provider::CanonStateSubscriptions; + use super::{FlashblocksConfig, payload::OpPayloadBuilder}; use crate::{ builders::{ @@ -16,14 +26,6 @@ use crate::{ metrics::OpRBuilderMetrics, traits::{NodeBounds, PoolBounds}, }; -use eyre::WrapErr as _; -use reth_basic_payload_builder::BasicPayloadJobGeneratorConfig; -use reth_node_api::NodeTypes; -use reth_node_builder::{BuilderContext, components::PayloadServiceBuilder}; -use reth_optimism_evm::OpEvmConfig; -use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; -use reth_provider::CanonStateSubscriptions; -use std::sync::Arc; pub struct FlashblocksServiceBuilder(pub BuilderConfig); @@ -74,19 +76,16 @@ impl FlashblocksServiceBuilder { vec![] }; - let p2p::NodeBuildResult { - node, - outgoing_message_tx, - mut incoming_message_rxs, - } = builder - .with_agent_version(AGENT_VERSION.to_string()) - .with_protocol(FLASHBLOCKS_STREAM_PROTOCOL) - .with_known_peers(known_peers) - .with_port(self.0.specific.p2p_port) - .with_cancellation_token(cancel.clone()) - .with_max_peer_count(self.0.specific.p2p_max_peer_count) - .try_build::() - .wrap_err("failed to build flashblocks p2p node")?; + let p2p::NodeBuildResult { node, outgoing_message_tx, mut incoming_message_rxs } = + builder + .with_agent_version(AGENT_VERSION.to_string()) + .with_protocol(FLASHBLOCKS_STREAM_PROTOCOL) + .with_known_peers(known_peers) + .with_port(self.0.specific.p2p_port) + .with_cancellation_token(cancel.clone()) + .with_max_peer_count(self.0.specific.p2p_max_peer_count) + .try_build::() + .wrap_err("failed to build flashblocks p2p node")?; let multiaddrs = node.multiaddrs(); ctx.task_executor().spawn(async move { if let Err(e) = node.run().await { @@ -156,10 +155,8 @@ impl FlashblocksServiceBuilder { ctx.task_executor() .spawn_critical("custom payload builder service", Box::pin(payload_service)); - ctx.task_executor().spawn_critical( - "flashblocks payload handler", - Box::pin(payload_handler.run()), - ); + ctx.task_executor() + .spawn_critical("flashblocks payload handler", Box::pin(payload_handler.run())); tracing::info!("Flashblocks payload builder service started"); Ok(payload_builder_handle) diff --git a/crates/builder/op-rbuilder/src/builders/flashblocks/wspub.rs b/crates/builder/op-rbuilder/src/builders/flashblocks/wspub.rs index 40760e5c..40e399c4 100644 --- a/crates/builder/op-rbuilder/src/builders/flashblocks/wspub.rs +++ b/crates/builder/op-rbuilder/src/builders/flashblocks/wspub.rs @@ -3,10 +3,11 @@ use core::{ net::SocketAddr, sync::atomic::{AtomicUsize, Ordering}, }; +use std::{io, net::TcpListener, sync::Arc}; + use base_flashtypes::FlashblocksPayloadV1; use futures::SinkExt; use futures_util::StreamExt; -use std::{io, net::TcpListener, sync::Arc}; use tokio::{ net::TcpStream, sync::{ @@ -51,12 +52,7 @@ impl WebSocketPublisher { Arc::clone(&subs), )); - Ok(Self { - sent, - subs, - term, - pipe, - }) + Ok(Self { sent, subs, term, pipe }) } pub(super) fn publish(&self, payload: &FlashblocksPayloadV1) -> io::Result { @@ -98,16 +94,12 @@ async fn listener_loop( sent: Arc, subs: Arc, ) { - listener - .set_nonblocking(true) - .expect("Failed to set TcpListener socket to non-blocking"); + listener.set_nonblocking(true).expect("Failed to set TcpListener socket to non-blocking"); let listener = tokio::net::TcpListener::from_std(listener) .expect("Failed to convert TcpListener to tokio TcpListener"); - let listen_addr = listener - .local_addr() - .expect("Failed to get local address of listener"); + let listen_addr = listener.local_addr().expect("Failed to get local address of listener"); tracing::info!("Flashblocks WebSocketPublisher listening on {listen_addr}"); let mut term = term; diff --git a/crates/builder/op-rbuilder/src/builders/generator.rs b/crates/builder/op-rbuilder/src/builders/generator.rs index d2f703de..6d95bccf 100644 --- a/crates/builder/op-rbuilder/src/builders/generator.rs +++ b/crates/builder/op-rbuilder/src/builders/generator.rs @@ -1,3 +1,8 @@ +use std::{ + sync::{Arc, Mutex}, + time::{SystemTime, UNIX_EPOCH}, +}; + use alloy_primitives::B256; use futures_util::{Future, FutureExt}; use reth_basic_payload_builder::{ @@ -12,10 +17,6 @@ use reth_primitives_traits::HeaderTy; use reth_provider::{BlockReaderIdExt, CanonStateNotification, StateProviderFactory}; use reth_revm::cached::CachedReads; use reth_tasks::TaskSpawner; -use std::{ - sync::{Arc, Mutex}, - time::{SystemTime, UNIX_EPOCH}, -}; use tokio::{ sync::{Notify, oneshot}, time::{Duration, Sleep}, @@ -108,10 +109,7 @@ impl BlockPayloadJobGenerator { /// Returns the pre-cached reads for the given parent header if it matches the cached state's /// block. fn maybe_pre_cached(&self, parent: B256) -> Option { - self.pre_cached - .as_ref() - .filter(|pc| pc.block == parent) - .map(|pc| pc.cached.clone()) + self.pre_cached.as_ref().filter(|pc| pc.block == parent).map(|pc| pc.cached.clone()) } } @@ -214,19 +212,13 @@ where if let Some(info) = acc.info.clone() { // we want pre cache existing accounts and their storage // this only includes changed accounts and storage but is better than nothing - let storage = acc - .storage - .iter() - .map(|(key, slot)| (*key, slot.present_value)) - .collect(); + let storage = + acc.storage.iter().map(|(key, slot)| (*key, slot.present_value)).collect(); cached.insert_account(addr, info, storage); } } - self.pre_cached = Some(PrecachedState { - block: committed.tip().hash(), - cached, - }); + self.pre_cached = Some(PrecachedState { block: committed.tip().hash(), cached }); } } @@ -321,11 +313,7 @@ where self.build_complete = Some(rx); let cached_reads = self.cached_reads.take().unwrap_or_default(); self.executor.spawn_blocking(Box::pin(async move { - let args = BuildArguments { - cached_reads, - config: payload_config, - cancel, - }; + let args = BuildArguments { cached_reads, config: payload_config, cancel }; let result = builder.try_build(args, cell).await; let _ = tx.send(result); @@ -394,10 +382,7 @@ pub(super) struct BlockCell { impl BlockCell { pub(super) fn new() -> Self { - Self { - inner: Arc::new(Mutex::new(None)), - notify: Arc::new(Notify::new()), - } + Self { inner: Arc::new(Mutex::new(None)), notify: Arc::new(Notify::new()) } } pub(super) fn set(&self, value: T) { @@ -444,10 +429,7 @@ impl Default for BlockCell { } fn job_deadline(unix_timestamp_secs: u64) -> std::time::Duration { - let unix_now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(); + let unix_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); // Safe subtraction that handles the case where timestamp is in the past let duration_until = unix_timestamp_secs.saturating_sub(unix_now); @@ -462,23 +444,24 @@ fn job_deadline(unix_timestamp_secs: u64) -> std::time::Duration { #[cfg(test)] mod tests { - use super::*; use alloy_eips::eip7685::Requests; use alloy_primitives::U256; use rand::rng; - use reth_tasks::TokioTaskExecutor; use reth_chain_state::ExecutedBlock; use reth_node_api::NodePrimitives; use reth_optimism_payload_builder::{OpPayloadPrimitives, payload::OpPayloadBuilderAttributes}; use reth_optimism_primitives::OpPrimitives; use reth_primitives::SealedBlock; use reth_provider::test_utils::MockEthProvider; + use reth_tasks::TokioTaskExecutor; use reth_testing_utils::generators::{BlockRangeParams, random_block_range}; use tokio::{ task, time::{Duration, sleep}, }; + use super::*; + #[tokio::test] async fn test_block_cell_wait_for_value() { let cell = BlockCell::new(); @@ -554,10 +537,7 @@ mod tests { impl MockBuilder { fn new() -> Self { - Self { - events: Arc::new(Mutex::new(vec![])), - _marker: std::marker::PhantomData, - } + Self { events: Arc::new(Mutex::new(vec![])), _marker: std::marker::PhantomData } } fn new_event(&self, event: BlockEvent) { @@ -665,10 +645,7 @@ mod tests { let blocks = random_block_range( &mut rng, start..=start + count - 1, - BlockRangeParams { - tx_count: 0..2, - ..Default::default() - }, + BlockRangeParams { tx_count: 0..2, ..Default::default() }, ); client.extend_blocks(blocks.iter().cloned().map(|b| (b.hash(), b.unseal()))); diff --git a/crates/builder/op-rbuilder/src/builders/mod.rs b/crates/builder/op-rbuilder/src/builders/mod.rs index 7950060a..d509ff9d 100644 --- a/crates/builder/op-rbuilder/src/builders/mod.rs +++ b/crates/builder/op-rbuilder/src/builders/mod.rs @@ -3,6 +3,7 @@ use core::{ fmt::Debug, time::Duration, }; + use reth_node_builder::components::PayloadServiceBuilder; use reth_optimism_evm::OpEvmConfig; use reth_optimism_payload_builder::config::{OpDAConfig, OpGasLimitConfig}; @@ -21,7 +22,6 @@ mod flashblocks; mod generator; mod standard; -use crate::tx_data_store::TxDataStore; pub use builder_tx::{ BuilderTransactionCtx, BuilderTransactionError, BuilderTransactions, InvalidContractDataError, SimulationSuccessResult, get_balance, get_nonce, @@ -30,6 +30,8 @@ pub use context::OpPayloadBuilderCtx; pub use flashblocks::FlashblocksBuilder; pub use standard::StandardBuilder; +use crate::tx_data_store::TxDataStore; + /// Defines the payload building mode for the OP builder. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum BuilderMode { diff --git a/crates/builder/op-rbuilder/src/builders/standard/builder_tx.rs b/crates/builder/op-rbuilder/src/builders/standard/builder_tx.rs index ececc887..bb50ad94 100644 --- a/crates/builder/op-rbuilder/src/builders/standard/builder_tx.rs +++ b/crates/builder/op-rbuilder/src/builders/standard/builder_tx.rs @@ -1,5 +1,6 @@ -use alloy_evm::Database; use core::fmt::Debug; + +use alloy_evm::Database; use reth_provider::StateProvider; use reth_revm::State; use revm::DatabaseRef; @@ -28,10 +29,7 @@ impl StandardBuilderTx { flashtestations_builder_tx: Option, ) -> Self { let base_builder_tx = BuilderTxBase::new(signer); - Self { - base_builder_tx, - flashtestations_builder_tx, - } + Self { base_builder_tx, flashtestations_builder_tx } } } diff --git a/crates/builder/op-rbuilder/src/builders/standard/payload.rs b/crates/builder/op-rbuilder/src/builders/standard/payload.rs index 40a4036e..d05c5ef3 100644 --- a/crates/builder/op-rbuilder/src/builders/standard/payload.rs +++ b/crates/builder/op-rbuilder/src/builders/standard/payload.rs @@ -1,11 +1,5 @@ -use super::super::context::OpPayloadBuilderCtx; -use crate::{ - builders::{BuilderConfig, BuilderTransactions, generator::BuildArguments}, - gas_limiter::AddressGasLimiter, - metrics::OpRBuilderMetrics, - primitives::reth::ExecutionInfo, - traits::{ClientBounds, PayloadTxsBounds, PoolBounds}, -}; +use std::{sync::Arc, time::Instant}; + use alloy_consensus::{ BlockBody, EMPTY_OMMER_ROOT_HASH, Header, constants::EMPTY_WITHDRAWALS, proofs, }; @@ -32,10 +26,18 @@ use reth_revm::{ use reth_transaction_pool::{ BestTransactions, BestTransactionsAttributes, PoolTransaction, TransactionPool, }; -use std::{sync::Arc, time::Instant}; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; +use super::super::context::OpPayloadBuilderCtx; +use crate::{ + builders::{BuilderConfig, BuilderTransactions, generator::BuildArguments}, + gas_limiter::AddressGasLimiter, + metrics::OpRBuilderMetrics, + primitives::reth::ExecutionInfo, + traits::{ClientBounds, PayloadTxsBounds, PoolBounds}, +}; + /// Optimism's payload builder #[derive(Debug, Clone)] pub(super) struct StandardOpPayloadBuilder { @@ -102,10 +104,7 @@ impl OpPayloadTransactions for () { ) -> impl PayloadTransactions { // TODO: once this issue is fixed we could remove without_updates and rely on regular impl // https://github.com/paradigmxyz/reth/issues/17325 - BestPayloadTransactions::new( - pool.best_transactions_with_attributes(attr) - .without_updates(), - ) + BestPayloadTransactions::new(pool.best_transactions_with_attributes(attr).without_updates()) } } @@ -133,16 +132,11 @@ where best_payload: _, } = args; - let args = BuildArguments { - cached_reads, - config, - cancel: CancellationToken::new(), - }; + 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) + self.best_transactions.best_transactions(pool.clone(), attrs) }) } @@ -160,16 +154,11 @@ where 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) + let args = + BuildArguments { config, cached_reads: Default::default(), cancel: Default::default() }; + self.build_payload(args, |_| NoopPayloadTransactions::::default())? + .into_payload() + .ok_or_else(|| PayloadBuilderError::MissingPayload) } } @@ -194,11 +183,7 @@ where ) -> Result, PayloadBuilderError> { let block_build_start_time = Instant::now(); - let BuildArguments { - mut cached_reads, - config, - cancel, - } = args; + let BuildArguments { mut cached_reads, config, cancel } = args; let chain_spec = self.client.chain_spec(); let timestamp = config.attributes.timestamp(); @@ -221,14 +206,8 @@ where 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, + 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, }; @@ -262,10 +241,7 @@ where let db = StateProviderDatabase::new(&state_provider); let metrics = ctx.metrics.clone(); if ctx.attributes().no_tx_pool { - let state = State::builder() - .with_database(db) - .with_bundle_update() - .build(); + let state = State::builder().with_database(db).with_bundle_update().build(); builder.build(state, &state_provider, ctx, self.builder_tx.clone()) } else { // sequencer mode we can reuse cachedreads from previous runs @@ -277,12 +253,8 @@ where } .map(|out| { let total_block_building_time = block_build_start_time.elapsed(); - metrics - .total_block_built_duration - .record(total_block_building_time); - metrics - .total_block_built_gauge - .set(total_block_building_time); + metrics.total_block_built_duration.record(total_block_building_time); + metrics.total_block_built_gauge.set(total_block_building_time); out.with_cached_reads(cached_reads) }) @@ -312,9 +284,7 @@ pub(super) struct OpBuilder<'a, Txs> { impl<'a, Txs> OpBuilder<'a, Txs> { fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self { - Self { - best: Box::new(best), - } + Self { best: Box::new(best) } } } @@ -400,12 +370,8 @@ impl OpBuilder<'_, Txs> { let best_txs_start_time = Instant::now(); let mut best_txs = best(ctx.best_transaction_attributes()); let transaction_pool_fetch_time = best_txs_start_time.elapsed(); - ctx.metrics - .transaction_pool_fetch_duration - .record(transaction_pool_fetch_time); - ctx.metrics - .transaction_pool_fetch_gauge - .set(transaction_pool_fetch_time); + ctx.metrics.transaction_pool_fetch_duration.record(transaction_pool_fetch_time); + ctx.metrics.transaction_pool_fetch_gauge.set(transaction_pool_fetch_time); if ctx .execute_best_transactions( @@ -434,19 +400,11 @@ impl OpBuilder<'_, Txs> { db.merge_transitions(BundleRetention::Reverts); let state_transition_merge_time = state_merge_start_time.elapsed(); - ctx.metrics - .state_transition_merge_duration - .record(state_transition_merge_time); - ctx.metrics - .state_transition_merge_gauge - .set(state_transition_merge_time); - - ctx.metrics - .payload_num_tx - .record(info.executed_transactions.len() as f64); - ctx.metrics - .payload_num_tx_gauge - .set(info.executed_transactions.len() as f64); + ctx.metrics.state_transition_merge_duration.record(state_transition_merge_time); + ctx.metrics.state_transition_merge_gauge.set(state_transition_merge_time); + + ctx.metrics.payload_num_tx.record(info.executed_transactions.len() as f64); + ctx.metrics.payload_num_tx_gauge.set(info.executed_transactions.len() as f64); let payload = ExecutedPayload { info }; @@ -465,10 +423,7 @@ impl OpBuilder<'_, Txs> { where BuilderTx: BuilderTransactions, { - let mut db = State::builder() - .with_database(state) - .with_bundle_update() - .build(); + let mut db = State::builder().with_database(state).with_bundle_update().build(); let ExecutedPayload { info } = match self.execute(&state_provider, &mut db, &ctx, builder_tx)? { BuildOutcomeKind::Better { payload } | BuildOutcomeKind::Freeze(payload) => payload, @@ -484,12 +439,8 @@ impl OpBuilder<'_, Txs> { // Need [Some] or [None] based on hardfork to match block hash. let (excess_blob_gas, blob_gas_used) = ctx.blob_fields(&info); - let execution_outcome = ExecutionOutcome::new( - db.take_bundle(), - vec![info.receipts], - block_number, - Vec::new(), - ); + let execution_outcome = + ExecutionOutcome::new(db.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( @@ -499,33 +450,26 @@ impl OpBuilder<'_, Txs> { ) }) .expect("Number is in range"); - let logs_bloom = execution_outcome - .block_logs_bloom(block_number) - .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 hashed_state = state_provider.hashed_post_state(execution_outcome.state()); let (state_root, trie_output) = { - state_provider - .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" - ); - })? + state_provider.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" + ); + })? }; let state_root_calculation_time = state_root_start_time.elapsed(); - ctx.metrics - .state_root_calculation_duration - .record(state_root_calculation_time); - ctx.metrics - .state_root_calculation_gauge - .set(state_root_calculation_time); + ctx.metrics.state_root_calculation_duration.record(state_root_calculation_time); + ctx.metrics.state_root_calculation_gauge.set(state_root_calculation_time); let (withdrawals_root, requests_hash) = if ctx.is_isthmus_active() { // withdrawals root field in block header is used for storage root of L2 predeploy @@ -600,19 +544,11 @@ impl OpBuilder<'_, Txs> { let no_tx_pool = ctx.attributes().no_tx_pool; - let payload = OpBuiltPayload::new( - ctx.payload_id(), - sealed_block, - info.total_fees, - Some(executed), - ); + let payload = + OpBuiltPayload::new(ctx.payload_id(), sealed_block, info.total_fees, Some(executed)); - ctx.metrics - .payload_byte_size - .record(InMemorySize::size(payload.block()) as f64); - ctx.metrics - .payload_byte_size_gauge - .set(InMemorySize::size(payload.block()) as f64); + ctx.metrics.payload_byte_size.record(InMemorySize::size(payload.block()) as f64); + ctx.metrics.payload_byte_size_gauge.set(InMemorySize::size(payload.block()) as f64); if no_tx_pool { // if `no_tx_pool` is set only transactions from the payload attributes will be included diff --git a/crates/builder/op-rbuilder/src/builders/standard/service.rs b/crates/builder/op-rbuilder/src/builders/standard/service.rs index 39484e86..f6b31cb2 100644 --- a/crates/builder/op-rbuilder/src/builders/standard/service.rs +++ b/crates/builder/op-rbuilder/src/builders/standard/service.rs @@ -53,8 +53,7 @@ impl StandardServiceBuilder { let (payload_service, payload_service_handle) = PayloadBuilderService::new(payload_generator, ctx.provider().canonical_state_stream()); - ctx.task_executor() - .spawn_critical("payload builder service", Box::pin(payload_service)); + ctx.task_executor().spawn_critical("payload builder service", Box::pin(payload_service)); Ok(payload_service_handle) } diff --git a/crates/builder/op-rbuilder/src/flashtestations/args.rs b/crates/builder/op-rbuilder/src/flashtestations/args.rs index 7856bb01..732917c8 100644 --- a/crates/builder/op-rbuilder/src/flashtestations/args.rs +++ b/crates/builder/op-rbuilder/src/flashtestations/args.rs @@ -18,11 +18,7 @@ pub struct FlashtestationsArgs { pub flashtestations_enabled: bool, /// Whether to use the debug HTTP service for quotes - #[arg( - long = "flashtestations.debug", - default_value = "false", - env = "FLASHTESTATIONS_DEBUG" - )] + #[arg(long = "flashtestations.debug", default_value = "false", env = "FLASHTESTATIONS_DEBUG")] pub debug: bool, // Debug static key for the tee key. DO NOT USE IN PRODUCTION @@ -42,10 +38,7 @@ pub struct FlashtestationsArgs { pub flashtestations_key_path: String, // Remote url for attestations - #[arg( - long = "flashtestations.quote-provider", - env = "FLASHTESTATIONS_QUOTE_PROVIDER" - )] + #[arg(long = "flashtestations.quote-provider", env = "FLASHTESTATIONS_QUOTE_PROVIDER")] pub quote_provider: Option, /// The rpc url to post the onchain attestation requests to @@ -88,9 +81,7 @@ pub struct FlashtestationsArgs { impl Default for FlashtestationsArgs { fn default() -> Self { let args = Cli::parse_from(["dummy", "node"]); - let Commands::Node(node_command) = args.command else { - unreachable!() - }; + let Commands::Node(node_command) = args.command else { unreachable!() }; node_command.ext.flashtestations } } diff --git a/crates/builder/op-rbuilder/src/flashtestations/attestation.rs b/crates/builder/op-rbuilder/src/flashtestations/attestation.rs index df712f98..c3de578b 100644 --- a/crates/builder/op-rbuilder/src/flashtestations/attestation.rs +++ b/crates/builder/op-rbuilder/src/flashtestations/attestation.rs @@ -59,10 +59,7 @@ pub struct RemoteAttestationProvider { impl RemoteAttestationProvider { pub fn new(service_url: String) -> Self { let client = Client::new(); - Self { - client, - service_url, - } + Self { client, service_url } } } @@ -89,9 +86,7 @@ impl RemoteAttestationProvider { pub fn get_attestation_provider(config: AttestationConfig) -> RemoteAttestationProvider { if config.debug { RemoteAttestationProvider::new( - config - .quote_provider - .unwrap_or(DEBUG_QUOTE_SERVICE_URL.to_string()), + config.quote_provider.unwrap_or(DEBUG_QUOTE_SERVICE_URL.to_string()), ) } else { RemoteAttestationProvider::new( @@ -210,9 +205,8 @@ pub fn compute_workload_id(raw_quote: &[u8]) -> eyre::Result<[u8; 32]> { #[cfg(test)] mod tests { - use crate::tests::WORKLOAD_ID; - use super::*; + use crate::tests::WORKLOAD_ID; #[test] fn test_compute_workload_id_from_test_quote() { @@ -223,9 +217,6 @@ mod tests { let workload_id = compute_workload_id(quote_output) .expect("failed to compute workload ID from test quote"); - assert_eq!( - workload_id, WORKLOAD_ID, - "workload ID mismatch for test quote" - ); + assert_eq!(workload_id, WORKLOAD_ID, "workload ID mismatch for test quote"); } } diff --git a/crates/builder/op-rbuilder/src/flashtestations/builder_tx.rs b/crates/builder/op-rbuilder/src/flashtestations/builder_tx.rs index 7651b846..7186caa5 100644 --- a/crates/builder/op-rbuilder/src/flashtestations/builder_tx.rs +++ b/crates/builder/op-rbuilder/src/flashtestations/builder_tx.rs @@ -1,17 +1,18 @@ +use core::fmt::Debug; +use std::sync::{Arc, atomic::AtomicBool}; + use alloy_eips::Encodable2718; use alloy_evm::Database; use alloy_op_evm::OpEvm; use alloy_primitives::{Address, B256, Bytes, Signature, U256, keccak256}; use alloy_rpc_types_eth::TransactionInput; use alloy_sol_types::{SolCall, SolEvent, SolValue}; -use core::fmt::Debug; use op_alloy_rpc_types::OpTransactionRequest; use reth_evm::{ConfigureEvm, Evm, precompiles::PrecompilesMap}; use reth_optimism_primitives::OpTransactionSigned; use reth_provider::StateProvider; use reth_revm::{State, database::StateProviderDatabase}; use revm::{DatabaseCommit, DatabaseRef, inspector::NoOpInspector}; -use std::sync::{Arc, atomic::AtomicBool}; use tracing::{debug, info, warn}; use crate::{ @@ -131,13 +132,9 @@ where ctx: &OpPayloadBuilderCtx, ) -> Result<(), BuilderTransactionError> { let state = StateProviderDatabase::new(state_provider.clone()); - let mut simulation_state = State::builder() - .with_database(state) - .with_bundle_update() - .build(); - let mut evm = ctx - .evm_config - .evm_with_env(&mut simulation_state, ctx.evm_env.clone()); + let mut simulation_state = + State::builder().with_database(state).with_bundle_update().build(); + let mut evm = ctx.evm_config.evm_with_env(&mut simulation_state, ctx.evm_env.clone()); evm.modify_cfg(|cfg| { cfg.disable_balance_check = true; cfg.disable_nonce_check = true; @@ -148,8 +145,7 @@ where let SimulationSuccessResult { output, .. } = self.flashtestations_contract_read(self.registry_address, calldata, ctx, &mut evm)?; if output.isValid { - self.registered - .store(true, std::sync::atomic::Ordering::SeqCst); + self.registered.store(true, std::sync::atomic::Ordering::SeqCst); } Ok(()) } @@ -160,9 +156,7 @@ where ctx: &OpPayloadBuilderCtx, evm: &mut OpEvm, ) -> Result { - let calldata = IERC20Permit::noncesCall { - owner: self.tee_service_signer.address, - }; + let calldata = IERC20Permit::noncesCall { owner: self.tee_service_signer.address }; let SimulationSuccessResult { output, .. } = self.flashtestations_contract_read(contract_address, calldata, ctx, evm)?; Ok(output) @@ -212,11 +206,7 @@ where deadline: U256::from(ctx.timestamp()), signature: signature.as_bytes().into(), }; - let SimulationSuccessResult { - gas_used, - state_changes, - .. - } = self.flashtestations_call( + let SimulationSuccessResult { gas_used, state_changes, .. } = self.flashtestations_call( self.registry_address, calldata.clone(), vec![TEEServiceRegistered::SIGNATURE_HASH], @@ -235,12 +225,7 @@ where op_alloy_flz::tx_estimated_size_fjord_bytes(signed_tx.encoded_2718().as_slice()); // commit the register transaction state so the block proof transaction can succeed evm.db_mut().commit(state_changes); - Ok(BuilderTransactionCtx { - gas_used, - da_size, - signed_tx, - is_top_of_block: false, - }) + Ok(BuilderTransactionCtx { gas_used, da_size, signed_tx, is_top_of_block: false }) } fn block_proof_permit_signature( @@ -311,12 +296,7 @@ where )?; let da_size = op_alloy_flz::tx_estimated_size_fjord_bytes(signed_tx.encoded_2718().as_slice()); - Ok(BuilderTransactionCtx { - gas_used, - da_size, - signed_tx, - is_top_of_block: false, - }) + Ok(BuilderTransactionCtx { gas_used, da_size, signed_tx, is_top_of_block: false }) } fn flashtestations_contract_read( @@ -357,9 +337,7 @@ where evm, ) } else { - Err(BuilderTransactionError::msg( - "invalid contract address for flashtestations", - )) + Err(BuilderTransactionError::msg("invalid contract address for flashtestations")) } } } diff --git a/crates/builder/op-rbuilder/src/flashtestations/service.rs b/crates/builder/op-rbuilder/src/flashtestations/service.rs index 73896119..5ae0c148 100644 --- a/crates/builder/op-rbuilder/src/flashtestations/service.rs +++ b/crates/builder/op-rbuilder/src/flashtestations/service.rs @@ -1,10 +1,12 @@ -use alloy_primitives::{B256, Bytes, keccak256}; use std::{ + fmt::Debug, fs::{self, OpenOptions}, io::Write, os::unix::fs::OpenOptionsExt, path::Path, }; + +use alloy_primitives::{B256, Bytes, keccak256}; use tracing::{info, warn}; use super::{ @@ -17,7 +19,6 @@ use crate::{ metrics::record_tee_metrics, tx_signer::{Signer, generate_key_from_seed, generate_signer}, }; -use std::fmt::Debug; pub async fn bootstrap_flashtestations( args: FlashtestationsArgs, @@ -33,14 +34,10 @@ where &args.debug_tee_key_seed, )?; - info!( - "Flashtestations TEE address: {}", - tee_service_signer.address - ); + info!("Flashtestations TEE address: {}", tee_service_signer.address); - let registry_address = args - .registry_address - .expect("registry address required when flashtestations enabled"); + let registry_address = + args.registry_address.expect("registry address required when flashtestations enabled"); let builder_policy_address = args .builder_policy_address .expect("builder policy address required when flashtestations enabled"); @@ -80,17 +77,10 @@ where // Use an external rpc when the builder is not the same as the builder actively building blocks onchain let registered = if let Some(rpc_url) = args.rpc_url { - let tx_manager = TxManager::new( - tee_service_signer, - builder_key, - rpc_url.clone(), - registry_address, - ); + let tx_manager = + TxManager::new(tee_service_signer, builder_key, rpc_url.clone(), registry_address); // Submit report onchain by registering the key of the tee service - match tx_manager - .register_tee_service(attestation.clone(), ext_data.clone()) - .await - { + match tx_manager.register_tee_service(attestation.clone(), ext_data.clone()).await { Ok(_) => true, Err(e) => { warn!(error = %e, "Failed to register tee service via rpc"); @@ -156,9 +146,8 @@ fn load_tee_key(path: &Path) -> Option { } info!("Loading TEE key from {:?}", path); - let key_hex = fs::read_to_string(path) - .inspect_err(|e| warn!("failed to read key file: {:?}", e)) - .ok()?; + let key_hex = + fs::read_to_string(path).inspect_err(|e| warn!("failed to read key file: {:?}", e)).ok()?; let secret_bytes = B256::try_from( hex::decode(key_hex.trim()) diff --git a/crates/builder/op-rbuilder/src/flashtestations/tx_manager.rs b/crates/builder/op-rbuilder/src/flashtestations/tx_manager.rs index d6412bf6..1f99bb0b 100644 --- a/crates/builder/op-rbuilder/src/flashtestations/tx_manager.rs +++ b/crates/builder/op-rbuilder/src/flashtestations/tx_manager.rs @@ -1,16 +1,16 @@ +use std::time::Duration; + use alloy_json_rpc::RpcError; use alloy_network::ReceiptResponse; use alloy_primitives::{Address, B256, Bytes, TxHash, TxKind, U256}; -use alloy_rpc_types_eth::TransactionRequest; -use alloy_sol_types::SolCall; -use alloy_transport::{TransportError, TransportErrorKind, TransportResult}; -use k256::ecdsa; -use std::time::Duration; - use alloy_provider::{ PendingTransactionBuilder, PendingTransactionError, Provider, ProviderBuilder, }; +use alloy_rpc_types_eth::TransactionRequest; use alloy_signer_local::PrivateKeySigner; +use alloy_sol_types::SolCall; +use alloy_transport::{TransportError, TransportErrorKind, TransportResult}; +use k256::ecdsa; use op_alloy_network::Optimism; use tracing::{debug, info, warn}; @@ -53,12 +53,7 @@ impl TxManager { rpc_url: String, registry_address: Address, ) -> Self { - Self { - tee_service_signer, - builder_signer, - rpc_url, - registry_address, - } + Self { tee_service_signer, builder_signer, rpc_url, registry_address } } pub async fn register_tee_service( @@ -84,9 +79,7 @@ impl TxManager { info!(target: "flashtestations", "submitting quote to registry at {}", self.registry_address); // Get permit nonce - let nonce_call = IERC20Permit::noncesCall { - owner: self.tee_service_signer.address, - }; + let nonce_call = IERC20Permit::noncesCall { owner: self.tee_service_signer.address }; let nonce_tx = TransactionRequest { to: Some(TxKind::Call(self.registry_address)), input: nonce_call.abi_encode().into(), @@ -96,10 +89,7 @@ impl TxManager { // Set deadline 1 hour from now let deadline = U256::from( - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs() + std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() + 3600, ); @@ -118,9 +108,8 @@ impl TxManager { let struct_hash = B256::from_slice(provider.call(struct_hash_tx.into()).await?.as_ref()); // Get typed data hash - let typed_hash_call = IFlashtestationRegistry::hashTypedDataV4Call { - structHash: struct_hash, - }; + let typed_hash_call = + IFlashtestationRegistry::hashTypedDataV4Call { structHash: struct_hash }; let typed_hash_tx = TransactionRequest { to: Some(TxKind::Call(self.registry_address)), input: typed_hash_call.abi_encode().into(), @@ -170,11 +159,7 @@ impl TxManager { debug!(target: "flashtestations", tx_hash = %tx_hash, "transaction submitted"); // Wait for funding transaction confirmation - match pending_tx - .with_timeout(Some(Duration::from_secs(30))) - .get_receipt() - .await - { + match pending_tx.with_timeout(Some(Duration::from_secs(30))).get_receipt().await { Ok(receipt) => { if receipt.status() { Ok(receipt.transaction_hash()) diff --git a/crates/builder/op-rbuilder/src/gas_limiter/args.rs b/crates/builder/op-rbuilder/src/gas_limiter/args.rs index ec7f8008..2896c489 100644 --- a/crates/builder/op-rbuilder/src/gas_limiter/args.rs +++ b/crates/builder/op-rbuilder/src/gas_limiter/args.rs @@ -7,19 +7,11 @@ pub struct GasLimiterArgs { pub gas_limiter_enabled: bool, /// Maximum gas per address in token bucket. Defaults to 10 million gas. - #[arg( - long = "gas-limiter.max-gas-per-address", - env, - default_value = "10000000" - )] + #[arg(long = "gas-limiter.max-gas-per-address", env, default_value = "10000000")] pub max_gas_per_address: u64, /// Gas refill rate per block. Defaults to 1 million gas per block. - #[arg( - long = "gas-limiter.refill-rate-per-block", - env, - default_value = "1000000" - )] + #[arg(long = "gas-limiter.refill-rate-per-block", env, default_value = "1000000")] pub refill_rate_per_block: u64, /// How many blocks to wait before cleaning up stale buckets for addresses. diff --git a/crates/builder/op-rbuilder/src/gas_limiter/error.rs b/crates/builder/op-rbuilder/src/gas_limiter/error.rs index a85b7f77..a42d3f00 100644 --- a/crates/builder/op-rbuilder/src/gas_limiter/error.rs +++ b/crates/builder/op-rbuilder/src/gas_limiter/error.rs @@ -5,9 +5,5 @@ pub enum GasLimitError { #[error( "Address {address} exceeded gas limit: {requested} gwei requested, {available} gwei available" )] - AddressLimitExceeded { - address: Address, - requested: u64, - available: u64, - }, + AddressLimitExceeded { address: Address, requested: u64, available: u64 }, } diff --git a/crates/builder/op-rbuilder/src/gas_limiter/metrics.rs b/crates/builder/op-rbuilder/src/gas_limiter/metrics.rs index f7898657..0eb3963b 100644 --- a/crates/builder/op-rbuilder/src/gas_limiter/metrics.rs +++ b/crates/builder/op-rbuilder/src/gas_limiter/metrics.rs @@ -40,8 +40,7 @@ impl GasLimiterMetrics { } pub(super) fn record_refresh(&self, removed_addresses: usize, duration: Duration) { - self.active_address_count - .decrement(removed_addresses as f64); + self.active_address_count.decrement(removed_addresses as f64); self.refresh_duration.record(duration); } } diff --git a/crates/builder/op-rbuilder/src/gas_limiter/mod.rs b/crates/builder/op-rbuilder/src/gas_limiter/mod.rs index 71daae7c..e5e5225e 100644 --- a/crates/builder/op-rbuilder/src/gas_limiter/mod.rs +++ b/crates/builder/op-rbuilder/src/gas_limiter/mod.rs @@ -31,9 +31,7 @@ struct TokenBucket { impl AddressGasLimiter { pub fn new(config: GasLimiterArgs) -> Self { - Self { - inner: AddressGasLimiterInner::try_new(config), - } + Self { inner: AddressGasLimiterInner::try_new(config) } } /// Check if there's enough gas for this address and consume it. Returns @@ -60,11 +58,7 @@ impl AddressGasLimiterInner { return None; } - Some(Self { - config, - address_buckets: Default::default(), - metrics: Default::default(), - }) + Some(Self { config, address_buckets: Default::default(), metrics: Default::default() }) } fn consume_gas_inner( @@ -108,16 +102,13 @@ impl AddressGasLimiterInner { let active_addresses = self.address_buckets.len(); self.address_buckets.iter_mut().for_each(|mut bucket| { - bucket.available = min( - bucket.capacity, - bucket.available + self.config.refill_rate_per_block, - ) + bucket.available = + min(bucket.capacity, bucket.available + self.config.refill_rate_per_block) }); // Only clean up stale buckets every `cleanup_interval` blocks if block_number.is_multiple_of(self.config.cleanup_interval) { - self.address_buckets - .retain(|_, bucket| bucket.available <= bucket.capacity); + self.address_buckets.retain(|_, bucket| bucket.available <= bucket.capacity); } active_addresses - self.address_buckets.len() @@ -127,25 +118,22 @@ impl AddressGasLimiterInner { let start = Instant::now(); let removed_addresses = self.refresh_inner(block_number); - self.metrics - .record_refresh(removed_addresses, start.elapsed()); + self.metrics.record_refresh(removed_addresses, start.elapsed()); } } impl TokenBucket { fn new(capacity: u64) -> Self { - Self { - capacity, - available: capacity, - } + Self { capacity, available: capacity } } } #[cfg(test)] mod tests { - use super::*; use alloy_primitives::Address; + use super::*; + fn create_test_config(max_gas: u64, refill_rate: u64, cleanup_interval: u64) -> GasLimiterArgs { GasLimiterArgs { gas_limiter_enabled: true, diff --git a/crates/builder/op-rbuilder/src/launcher.rs b/crates/builder/op-rbuilder/src/launcher.rs index 86c73110..d77f9722 100644 --- a/crates/builder/op-rbuilder/src/launcher.rs +++ b/crates/builder/op-rbuilder/src/launcher.rs @@ -1,6 +1,19 @@ +use core::fmt::Debug; +use std::{marker::PhantomData, sync::Arc}; + use eyre::Result; -use reth_node_builder::WithLaunchContext; +use moka::future::Cache; +use reth_cli_commands::launcher::Launcher; +use reth_db::mdbx::DatabaseEnv; +use reth_node_builder::{NodeBuilder, WithLaunchContext}; +use reth_optimism_chainspec::OpChainSpec; +use reth_optimism_cli::chainspec::OpChainSpecParser; +use reth_optimism_node::{ + OpNode, + node::{OpAddOns, OpAddOnsBuilder, OpEngineValidatorBuilder, OpPoolBuilder}, +}; use reth_optimism_rpc::OpEthApiBuilder; +use reth_transaction_pool::TransactionPool; use crate::{ args::*, @@ -12,19 +25,6 @@ use crate::{ tx::FBPooledTransaction, tx_data_store::{BaseApiExtServer, TxDataStoreExt}, }; -use core::fmt::Debug; -use moka::future::Cache; -use reth_cli_commands::launcher::Launcher; -use reth_db::mdbx::DatabaseEnv; -use reth_optimism_chainspec::OpChainSpec; -use reth_optimism_cli::chainspec::OpChainSpecParser; -use reth_node_builder::NodeBuilder; -use reth_optimism_node::{ - OpNode, - node::{OpAddOns, OpAddOnsBuilder, OpEngineValidatorBuilder, OpPoolBuilder}, -}; -use reth_transaction_pool::TransactionPool; -use std::{marker::PhantomData, sync::Arc}; pub fn launch() -> Result<()> { let cli = Cli::parsed(); @@ -74,9 +74,7 @@ where B: PayloadBuilder, { pub fn new() -> Self { - Self { - _builder: PhantomData, - } + Self { _builder: PhantomData } } } @@ -163,13 +161,11 @@ where reverted_cache, ); - ctx.modules - .add_or_replace_configured(revert_protection_ext.into_rpc())?; + ctx.modules.add_or_replace_configured(revert_protection_ext.into_rpc())?; } let tx_data_store_ext = TxDataStoreExt::new(tx_data_store); - ctx.modules - .add_or_replace_configured(tx_data_store_ext.into_rpc())?; + ctx.modules.add_or_replace_configured(tx_data_store_ext.into_rpc())?; Ok(()) }) diff --git a/crates/builder/op-rbuilder/src/metrics.rs b/crates/builder/op-rbuilder/src/metrics.rs index 5d72d9ee..c750135a 100644 --- a/crates/builder/op-rbuilder/src/metrics.rs +++ b/crates/builder/op-rbuilder/src/metrics.rs @@ -203,22 +203,16 @@ impl OpRBuilderMetrics { num_bundles_reverted: impl IntoF64, reverted_gas_used: impl IntoF64, ) { - self.payload_transaction_simulation_duration - .record(payload_transaction_simulation_time); - self.payload_transaction_simulation_gauge - .set(payload_transaction_simulation_time); + self.payload_transaction_simulation_duration.record(payload_transaction_simulation_time); + self.payload_transaction_simulation_gauge.set(payload_transaction_simulation_time); self.payload_num_tx_considered.record(num_txs_considered); self.payload_num_tx_considered_gauge.set(num_txs_considered); self.payload_num_tx_simulated.record(num_txs_simulated); self.payload_num_tx_simulated_gauge.set(num_txs_simulated); - self.payload_num_tx_simulated_success - .record(num_txs_simulated_success); - self.payload_num_tx_simulated_success_gauge - .set(num_txs_simulated_success); - self.payload_num_tx_simulated_fail - .record(num_txs_simulated_fail); - self.payload_num_tx_simulated_fail_gauge - .set(num_txs_simulated_fail); + self.payload_num_tx_simulated_success.record(num_txs_simulated_success); + self.payload_num_tx_simulated_success_gauge.set(num_txs_simulated_success); + self.payload_num_tx_simulated_fail.record(num_txs_simulated_fail); + self.payload_num_tx_simulated_fail_gauge.set(num_txs_simulated_fail); self.bundles_reverted.record(num_bundles_reverted); self.payload_reverted_tx_gas_used.set(reverted_gas_used); } diff --git a/crates/builder/op-rbuilder/src/mock_tx.rs b/crates/builder/op-rbuilder/src/mock_tx.rs index ea9697c4..d37c3b29 100644 --- a/crates/builder/op-rbuilder/src/mock_tx.rs +++ b/crates/builder/op-rbuilder/src/mock_tx.rs @@ -1,4 +1,5 @@ -use crate::tx::MaybeFlashblockFilter; +use std::{sync::Arc, time::Instant}; + use alloy_consensus::{ EthereumTxEnvelope, TxEip4844, TxEip4844WithSidecar, TxType, error::ValueError, transaction::Recovered, @@ -19,7 +20,8 @@ use reth_transaction_pool::{ identifier::TransactionId, test_utils::{MockTransaction, MockTransactionFactory}, }; -use std::{sync::Arc, time::Instant}; + +use crate::tx::MaybeFlashblockFilter; /// A factory for creating and managing various types of mock transactions. #[derive(Debug, Default)] @@ -221,42 +223,26 @@ impl alloy_consensus::Transaction for MockFbTransaction { match &self.inner { MockTransaction::Legacy { gas_price, .. } | MockTransaction::Eip2930 { gas_price, .. } => *gas_price, - MockTransaction::Eip1559 { - max_fee_per_gas, .. - } - | MockTransaction::Eip4844 { - max_fee_per_gas, .. - } - | MockTransaction::Eip7702 { - max_fee_per_gas, .. - } => *max_fee_per_gas, + MockTransaction::Eip1559 { max_fee_per_gas, .. } + | MockTransaction::Eip4844 { max_fee_per_gas, .. } + | MockTransaction::Eip7702 { max_fee_per_gas, .. } => *max_fee_per_gas, } } fn max_priority_fee_per_gas(&self) -> Option { match &self.inner { MockTransaction::Legacy { .. } | MockTransaction::Eip2930 { .. } => None, - MockTransaction::Eip1559 { - max_priority_fee_per_gas, - .. - } - | MockTransaction::Eip4844 { - max_priority_fee_per_gas, - .. + MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } + | MockTransaction::Eip4844 { max_priority_fee_per_gas, .. } + | MockTransaction::Eip7702 { max_priority_fee_per_gas, .. } => { + Some(*max_priority_fee_per_gas) } - | MockTransaction::Eip7702 { - max_priority_fee_per_gas, - .. - } => Some(*max_priority_fee_per_gas), } } fn max_fee_per_blob_gas(&self) -> Option { match &self.inner { - MockTransaction::Eip4844 { - max_fee_per_blob_gas, - .. - } => Some(*max_fee_per_blob_gas), + MockTransaction::Eip4844 { max_fee_per_blob_gas, .. } => Some(*max_fee_per_blob_gas), _ => None, } } @@ -265,18 +251,11 @@ impl alloy_consensus::Transaction for MockFbTransaction { match &self.inner { MockTransaction::Legacy { gas_price, .. } | MockTransaction::Eip2930 { gas_price, .. } => *gas_price, - MockTransaction::Eip1559 { - max_priority_fee_per_gas, - .. + MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } + | MockTransaction::Eip4844 { max_priority_fee_per_gas, .. } + | MockTransaction::Eip7702 { max_priority_fee_per_gas, .. } => { + *max_priority_fee_per_gas } - | MockTransaction::Eip4844 { - max_priority_fee_per_gas, - .. - } - | MockTransaction::Eip7702 { - max_priority_fee_per_gas, - .. - } => *max_priority_fee_per_gas, } } @@ -302,10 +281,7 @@ impl alloy_consensus::Transaction for MockFbTransaction { } fn is_dynamic_fee(&self) -> bool { - !matches!( - self.inner, - MockTransaction::Legacy { .. } | MockTransaction::Eip2930 { .. } - ) + !matches!(self.inner, MockTransaction::Legacy { .. } | MockTransaction::Eip2930 { .. }) } fn kind(&self) -> TxKind { @@ -345,40 +321,23 @@ impl alloy_consensus::Transaction for MockFbTransaction { fn access_list(&self) -> Option<&AccessList> { match &self.inner { MockTransaction::Legacy { .. } => None, - MockTransaction::Eip1559 { - access_list: accesslist, - .. - } - | MockTransaction::Eip4844 { - access_list: accesslist, - .. - } - | MockTransaction::Eip2930 { - access_list: accesslist, - .. - } - | MockTransaction::Eip7702 { - access_list: accesslist, - .. - } => Some(accesslist), + MockTransaction::Eip1559 { access_list: accesslist, .. } + | MockTransaction::Eip4844 { access_list: accesslist, .. } + | MockTransaction::Eip2930 { access_list: accesslist, .. } + | MockTransaction::Eip7702 { access_list: accesslist, .. } => Some(accesslist), } } fn blob_versioned_hashes(&self) -> Option<&[B256]> { match &self.inner { - MockTransaction::Eip4844 { - blob_versioned_hashes, - .. - } => Some(blob_versioned_hashes), + MockTransaction::Eip4844 { blob_versioned_hashes, .. } => Some(blob_versioned_hashes), _ => None, } } fn authorization_list(&self) -> Option<&[SignedAuthorization]> { match &self.inner { - MockTransaction::Eip7702 { - authorization_list, .. - } => Some(authorization_list), + MockTransaction::Eip7702 { authorization_list, .. } => Some(authorization_list), _ => None, } } @@ -422,9 +381,7 @@ impl EthPoolTransaction for MockFbTransaction { ) -> Result<(), alloy_eips::eip4844::BlobTransactionValidationError> { match &self.inner { MockTransaction::Eip4844 { .. } => Ok(()), - _ => Err(BlobTransactionValidationError::NotBlobTransaction( - self.inner.tx_type(), - )), + _ => Err(BlobTransactionValidationError::NotBlobTransaction(self.inner.tx_type())), } } } diff --git a/crates/builder/op-rbuilder/src/monitor_tx_pool.rs b/crates/builder/op-rbuilder/src/monitor_tx_pool.rs index 00b341f2..62103026 100644 --- a/crates/builder/op-rbuilder/src/monitor_tx_pool.rs +++ b/crates/builder/op-rbuilder/src/monitor_tx_pool.rs @@ -1,10 +1,11 @@ -use crate::tx::FBPooledTransaction; use alloy_primitives::B256; use futures_util::StreamExt; use moka::future::Cache; use reth_transaction_pool::{AllTransactionsEvents, FullTransactionEvent}; use tracing::info; +use crate::tx::FBPooledTransaction; + pub(crate) async fn monitor_tx_pool( mut new_transactions: AllTransactionsEvents, reverted_cache: Cache, @@ -35,20 +36,14 @@ async fn transaction_event_log( "Transaction event received" ) } - FullTransactionEvent::Mined { - tx_hash, - block_hash, - } => info!( + FullTransactionEvent::Mined { tx_hash, block_hash } => info!( target = "monitoring", tx_hash = tx_hash.to_string(), kind = "mined", block_hash = block_hash.to_string(), "Transaction event received" ), - FullTransactionEvent::Replaced { - transaction, - replaced_by, - } => info!( + FullTransactionEvent::Replaced { transaction, replaced_by } => info!( target = "monitoring", tx_hash = transaction.hash().to_string(), kind = "replaced", diff --git a/crates/builder/op-rbuilder/src/primitives/bundle.rs b/crates/builder/op-rbuilder/src/primitives/bundle.rs index 6e4c471b..45761071 100644 --- a/crates/builder/op-rbuilder/src/primitives/bundle.rs +++ b/crates/builder/op-rbuilder/src/primitives/bundle.rs @@ -103,11 +103,7 @@ pub struct Bundle { /// builder node's clock, which may not be perfectly synchronized with /// network time. Block number constraints are preferred for deterministic /// behavior. - #[serde( - default, - rename = "minTimestamp", - skip_serializing_if = "Option::is_none" - )] + #[serde(default, rename = "minTimestamp", skip_serializing_if = "Option::is_none")] pub min_timestamp: Option, /// Maximum timestamp (Unix epoch seconds) for bundle inclusion. @@ -116,11 +112,7 @@ pub struct Bundle { /// builder node's clock, which may not be perfectly synchronized with /// network time. Block number constraints are preferred for deterministic /// behavior. - #[serde( - default, - rename = "maxTimestamp", - skip_serializing_if = "Option::is_none" - )] + #[serde(default, rename = "maxTimestamp", skip_serializing_if = "Option::is_none")] pub max_timestamp: Option, } @@ -142,11 +134,7 @@ pub enum BundleConditionalError { #[error( "block_number_max ({max}) is too high (current: {current}, max allowed: {max_allowed})" )] - MaxBlockTooHigh { - max: u64, - current: u64, - max_allowed: u64, - }, + MaxBlockTooHigh { max: u64, current: u64, max_allowed: u64 }, /// When no explicit maximum block number is provided, the system uses /// `current_block + MAX_BLOCK_RANGE_BLOCKS` as the default maximum. This /// error occurs when the specified minimum exceeds this default maximum. @@ -258,22 +246,13 @@ mod tests { #[test] fn test_bundle_conditional_no_bounds() { - let bundle = Bundle { - transactions: vec![], - ..Default::default() - }; + let bundle = Bundle { transactions: vec![], ..Default::default() }; let last_block = 1000; - let result = bundle - .conditional(last_block) - .unwrap() - .transaction_conditional; + let result = bundle.conditional(last_block).unwrap().transaction_conditional; assert_eq!(result.block_number_min, None); - assert_eq!( - result.block_number_max, - Some(last_block + MAX_BLOCK_RANGE_BLOCKS) - ); + assert_eq!(result.block_number_max, Some(last_block + MAX_BLOCK_RANGE_BLOCKS)); } #[test] @@ -285,10 +264,7 @@ mod tests { }; let last_block = 1000; - let result = bundle - .conditional(last_block) - .unwrap() - .transaction_conditional; + let result = bundle.conditional(last_block).unwrap().transaction_conditional; assert_eq!(result.block_number_min, Some(1002)); assert_eq!(result.block_number_max, Some(1005)); @@ -307,38 +283,26 @@ mod tests { assert!(matches!( result, - Err(BundleConditionalError::MinGreaterThanMax { - min: 1010, - max: 1005 - }) + Err(BundleConditionalError::MinGreaterThanMax { min: 1010, max: 1005 }) )); } #[test] fn test_bundle_conditional_max_in_past() { - let bundle = Bundle { - block_number_max: Some(999), - ..Default::default() - }; + let bundle = Bundle { block_number_max: Some(999), ..Default::default() }; let last_block = 1000; let result = bundle.conditional(last_block); assert!(matches!( result, - Err(BundleConditionalError::MaxBlockInPast { - max: 999, - current: 1000 - }) + Err(BundleConditionalError::MaxBlockInPast { max: 999, current: 1000 }) )); } #[test] fn test_bundle_conditional_max_too_high() { - let bundle = Bundle { - block_number_max: Some(1020), - ..Default::default() - }; + let bundle = Bundle { block_number_max: Some(1020), ..Default::default() }; let last_block = 1000; let result = bundle.conditional(last_block); @@ -355,35 +319,23 @@ mod tests { #[test] fn test_bundle_conditional_min_too_high_for_default_range() { - let bundle = Bundle { - block_number_min: Some(1015), - ..Default::default() - }; + let bundle = Bundle { block_number_min: Some(1015), ..Default::default() }; let last_block = 1000; let result = bundle.conditional(last_block); assert!(matches!( result, - Err(BundleConditionalError::MinTooHighForDefaultRange { - min: 1015, - max_allowed: 1010 - }) + Err(BundleConditionalError::MinTooHighForDefaultRange { min: 1015, max_allowed: 1010 }) )); } #[test] fn test_bundle_conditional_with_only_min() { - let bundle = Bundle { - block_number_min: Some(1005), - ..Default::default() - }; + let bundle = Bundle { block_number_min: Some(1005), ..Default::default() }; let last_block = 1000; - let result = bundle - .conditional(last_block) - .unwrap() - .transaction_conditional; + let result = bundle.conditional(last_block).unwrap().transaction_conditional; assert_eq!(result.block_number_min, Some(1005)); assert_eq!(result.block_number_max, Some(1010)); // last_block + MAX_BLOCK_RANGE_BLOCKS @@ -391,16 +343,10 @@ mod tests { #[test] fn test_bundle_conditional_with_only_max() { - let bundle = Bundle { - block_number_max: Some(1008), - ..Default::default() - }; + let bundle = Bundle { block_number_max: Some(1008), ..Default::default() }; let last_block = 1000; - let result = bundle - .conditional(last_block) - .unwrap() - .transaction_conditional; + let result = bundle.conditional(last_block).unwrap().transaction_conditional; assert_eq!(result.block_number_min, None); assert_eq!(result.block_number_max, Some(1008)); @@ -408,16 +354,10 @@ mod tests { #[test] fn test_bundle_conditional_min_lower_than_last_block() { - let bundle = Bundle { - block_number_min: Some(999), - ..Default::default() - }; + let bundle = Bundle { block_number_min: Some(999), ..Default::default() }; let last_block = 1000; - let result = bundle - .conditional(last_block) - .unwrap() - .transaction_conditional; + let result = bundle.conditional(last_block).unwrap().transaction_conditional; assert_eq!(result.block_number_min, Some(999)); assert_eq!(result.block_number_max, Some(1010)); @@ -457,10 +397,7 @@ mod tests { #[test] fn test_bundle_conditional_with_only_flashblock_min() { - let bundle = Bundle { - flashblock_number_min: Some(100), - ..Default::default() - }; + let bundle = Bundle { flashblock_number_min: Some(100), ..Default::default() }; let last_block = 1000; let result = bundle.conditional(last_block).unwrap(); @@ -471,10 +408,7 @@ mod tests { #[test] fn test_bundle_conditional_with_only_flashblock_max() { - let bundle = Bundle { - flashblock_number_max: Some(105), - ..Default::default() - }; + let bundle = Bundle { flashblock_number_max: Some(105), ..Default::default() }; let last_block = 1000; let result = bundle.conditional(last_block).unwrap(); diff --git a/crates/builder/op-rbuilder/src/primitives/reth/engine_api_builder.rs b/crates/builder/op-rbuilder/src/primitives/reth/engine_api_builder.rs index 6e6642b1..aaf0eaa6 100644 --- a/crates/builder/op-rbuilder/src/primitives/reth/engine_api_builder.rs +++ b/crates/builder/op-rbuilder/src/primitives/reth/engine_api_builder.rs @@ -1,15 +1,5 @@ //! RPC component builder -use reth_node_api::{AddOnsContext, NodeTypes}; -use reth_node_builder::rpc::{EngineApiBuilder, PayloadValidatorBuilder}; -use reth_node_core::version::{CLIENT_CODE, version_metadata}; -use reth_optimism_node::OpEngineTypes; -pub use reth_optimism_rpc::OpEngineApi; -use reth_optimism_rpc::engine::OP_ENGINE_CAPABILITIES; -use reth_payload_builder::PayloadStore; -use reth_rpc_engine_api::EngineCapabilities; - -use crate::traits::NodeComponents; use alloy_eips::eip7685::Requests; use alloy_primitives::{B256, BlockHash, U64}; use alloy_rpc_types_engine::{ @@ -22,13 +12,21 @@ use op_alloy_rpc_types_engine::{ OpExecutionPayloadEnvelopeV3, OpExecutionPayloadEnvelopeV4, OpExecutionPayloadV4, OpPayloadAttributes, ProtocolVersion, SuperchainSignal, }; -use reth_node_api::{EngineApiValidator, EngineTypes}; +use reth_node_api::{AddOnsContext, EngineApiValidator, EngineTypes, NodeTypes}; +use reth_node_builder::rpc::{EngineApiBuilder, PayloadValidatorBuilder}; +use reth_node_core::version::{CLIENT_CODE, version_metadata}; use reth_optimism_chainspec::OpChainSpec; -use reth_optimism_rpc::OpEngineApiServer; +use reth_optimism_node::OpEngineTypes; +pub use reth_optimism_rpc::OpEngineApi; +use reth_optimism_rpc::{OpEngineApiServer, engine::OP_ENGINE_CAPABILITIES}; +use reth_payload_builder::PayloadStore; use reth_rpc_api::IntoEngineApiRpcModule; +use reth_rpc_engine_api::EngineCapabilities; use reth_storage_api::{BlockReader, HeaderProvider, StateProviderFactory}; use reth_transaction_pool::TransactionPool; +use crate::traits::NodeComponents; + /// Builder for basic [`OpEngineApi`] implementation. #[derive(Debug, Clone)] pub struct OpEngineApiBuilder { @@ -40,9 +38,7 @@ where EV: Default, { fn default() -> Self { - Self { - engine_validator_builder: EV::default(), - } + Self { engine_validator_builder: EV::default() } } } @@ -55,9 +51,7 @@ where type EngineApi = OpEngineApiExt; async fn build_engine_api(self, ctx: &AddOnsContext<'_, N>) -> eyre::Result { - let Self { - engine_validator_builder, - } = self; + let Self { engine_validator_builder } = self; let engine_validator = engine_validator_builder.build(ctx).await?; let client = ClientVersionV1 { @@ -116,9 +110,7 @@ where versioned_hashes: Vec, parent_beacon_block_root: B256, ) -> RpcResult { - self.inner - .new_payload_v3(payload, versioned_hashes, parent_beacon_block_root) - .await + self.inner.new_payload_v3(payload, versioned_hashes, parent_beacon_block_root).await } async fn new_payload_v4( @@ -129,12 +121,7 @@ where execution_requests: Requests, ) -> RpcResult { self.inner - .new_payload_v4( - payload, - versioned_hashes, - parent_beacon_block_root, - execution_requests, - ) + .new_payload_v4(payload, versioned_hashes, parent_beacon_block_root, execution_requests) .await } @@ -143,9 +130,7 @@ where fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult { - self.inner - .fork_choice_updated_v1(fork_choice_state, payload_attributes) - .await + self.inner.fork_choice_updated_v1(fork_choice_state, payload_attributes).await } async fn fork_choice_updated_v2( @@ -153,9 +138,7 @@ where fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult { - self.inner - .fork_choice_updated_v2(fork_choice_state, payload_attributes) - .await + self.inner.fork_choice_updated_v2(fork_choice_state, payload_attributes).await } async fn fork_choice_updated_v3( @@ -163,9 +146,7 @@ where fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult { - self.inner - .fork_choice_updated_v3(fork_choice_state, payload_attributes) - .await + self.inner.fork_choice_updated_v3(fork_choice_state, payload_attributes).await } async fn get_payload_v2( @@ -201,9 +182,7 @@ where start: U64, count: U64, ) -> RpcResult { - self.inner - .get_payload_bodies_by_range_v1(start, count) - .await + self.inner.get_payload_bodies_by_range_v1(start, count).await } async fn signal_superchain_v1(&self, signal: SuperchainSignal) -> RpcResult { diff --git a/crates/builder/op-rbuilder/src/primitives/reth/execution.rs b/crates/builder/op-rbuilder/src/primitives/reth/execution.rs index 7865a1c8..194dcae1 100644 --- a/crates/builder/op-rbuilder/src/primitives/reth/execution.rs +++ b/crates/builder/op-rbuilder/src/primitives/reth/execution.rs @@ -1,6 +1,7 @@ //! Heavily influenced by [reth](https://github.com/paradigmxyz/reth/blob/1e965caf5fa176f244a31c0d2662ba1b590938db/crates/optimism/payload/src/builder.rs#L570) -use alloy_primitives::{Address, U256}; use core::fmt::Debug; + +use alloy_primitives::{Address, U256}; use derive_more::Display; use op_revm::OpTransactionError; use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; diff --git a/crates/builder/op-rbuilder/src/primitives/telemetry.rs b/crates/builder/op-rbuilder/src/primitives/telemetry.rs index dfedbcc5..ffdb50a9 100644 --- a/crates/builder/op-rbuilder/src/primitives/telemetry.rs +++ b/crates/builder/op-rbuilder/src/primitives/telemetry.rs @@ -1,7 +1,8 @@ -use crate::args::TelemetryArgs; use tracing_subscriber::{Layer, filter::Targets}; use url::Url; +use crate::args::TelemetryArgs; + /// Setup telemetry layer with sampling and custom endpoint configuration pub fn setup_telemetry_layer( args: &TelemetryArgs, diff --git a/crates/builder/op-rbuilder/src/revert_protection.rs b/crates/builder/op-rbuilder/src/revert_protection.rs index f45eaea3..946a324e 100644 --- a/crates/builder/op-rbuilder/src/revert_protection.rs +++ b/crates/builder/op-rbuilder/src/revert_protection.rs @@ -1,10 +1,5 @@ use std::{sync::Arc, time::Instant}; -use crate::{ - metrics::OpRBuilderMetrics, - primitives::bundle::{Bundle, BundleResult}, - tx::{FBPooledTransaction, MaybeFlashblockFilter, MaybeRevertingTransaction}, -}; use alloy_json_rpc::RpcObject; use alloy_primitives::B256; use jsonrpsee::{ @@ -19,6 +14,12 @@ use reth_rpc_eth_types::{EthApiError, utils::recover_raw_transaction}; use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool}; use tracing::error; +use crate::{ + metrics::OpRBuilderMetrics, + primitives::bundle::{Bundle, BundleResult}, + tx::{FBPooledTransaction, MaybeFlashblockFilter, MaybeRevertingTransaction}, +}; + // Namespace overrides for revert protection support #[cfg_attr(not(test), rpc(server, namespace = "eth"))] #[cfg_attr(test, rpc(server, client, namespace = "eth"))] @@ -83,9 +84,7 @@ where self.metrics.failed_bundles.increment(1); } - self.metrics - .bundle_receive_duration - .record(request_start_time.elapsed()); + self.metrics.bundle_receive_duration.record(request_start_time.elapsed()); bundle_result } @@ -98,10 +97,8 @@ where Ok(Some(receipt)) } else if self.reverted_cache.get(&hash).await.is_some() { // Found the transaction in the reverted cache - Err( - EthApiError::InvalidParams("the transaction was dropped from the pool".into()) - .into(), - ) + Err(EthApiError::InvalidParams("the transaction was dropped from the pool".into()) + .into()) } else { Ok(None) } @@ -115,10 +112,8 @@ where Eth: FullEthApi + Send + Sync + Clone + 'static, { async fn send_bundle_inner(&self, bundle: Bundle) -> RpcResult { - let last_block_number = self - .provider - .best_block_number() - .map_err(|_e| EthApiError::InternalEthError)?; + let last_block_number = + self.provider.best_block_number().map_err(|_e| EthApiError::InternalEthError)?; // Only one transaction in the bundle is expected let bundle_transaction = match bundle.transactions.len() { @@ -137,9 +132,7 @@ where } }; - let conditional = bundle - .conditional(last_block_number) - .map_err(EthApiError::from)?; + let conditional = bundle.conditional(last_block_number).map_err(EthApiError::from)?; let recovered = recover_raw_transaction(&bundle_transaction)?; let pool_transaction = @@ -155,9 +148,7 @@ where .await .map_err(EthApiError::from)?; - let result = BundleResult { - bundle_hash: outcome.hash, - }; + let result = BundleResult { bundle_hash: outcome.hash }; Ok(result) } } diff --git a/crates/builder/op-rbuilder/src/tests/backrun.rs b/crates/builder/op-rbuilder/src/tests/backrun.rs index a1522a3c..a4a499bc 100644 --- a/crates/builder/op-rbuilder/src/tests/backrun.rs +++ b/crates/builder/op-rbuilder/src/tests/backrun.rs @@ -1,11 +1,12 @@ -use crate::tests::{ChainDriverExt, LocalInstance, framework::ONE_ETH}; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{TxHash, U256}; use alloy_provider::Provider; -use macros::rb_test; use base_bundles::{AcceptedBundle, MeterBundleResponse}; +use macros::rb_test; use uuid::Uuid; +use crate::tests::{ChainDriverExt, LocalInstance, framework::ONE_ETH}; + /// Tests that backrun bundles are all-or-nothing: /// - If any backrun tx in a bundle reverts, the entire bundle is excluded /// - Even successful txs in the bundle are not included @@ -25,9 +26,7 @@ async fn backrun_bundle_all_or_nothing_revert(rbuilder: LocalInstance) -> eyre:: // Send to mempool manually (send() doesn't return the Recovered tx) let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; // 2. Create backrun transactions: // - backrun_ok: valid tx with HIGH priority (executes first, succeeds) @@ -91,10 +90,7 @@ async fn backrun_bundle_all_or_nothing_revert(rbuilder: LocalInstance) -> eyre:: let tx_hashes: Vec<_> = block.transactions.hashes().collect(); // Target tx SHOULD be in block (it was in mempool independently) - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx should be included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx should be included in block"); // backrun_ok should NOT be in block (all-or-nothing: bundle failed) assert!( @@ -103,10 +99,7 @@ async fn backrun_bundle_all_or_nothing_revert(rbuilder: LocalInstance) -> eyre:: ); // backrun_revert should NOT be in block (it caused the revert) - assert!( - !tx_hashes.contains(&backrun_revert_hash), - "backrun_revert should NOT be in block" - ); + assert!(!tx_hashes.contains(&backrun_revert_hash), "backrun_revert should NOT be in block"); Ok(()) } @@ -130,9 +123,7 @@ async fn backrun_bundles_sorted_by_total_fee(rbuilder: LocalInstance) -> eyre::R // Send to mempool manually let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; // 2. Create Bundle A with HIGH total priority fee // Two txs: 60 + 50 = 110 total @@ -225,14 +216,8 @@ async fn backrun_bundles_sorted_by_total_fee(rbuilder: LocalInstance) -> eyre::R }; // Insert in "wrong" order - B first, then A - rbuilder - .tx_data_store() - .insert_backrun_bundle(bundle_b) - .expect("Failed to insert bundle B"); - rbuilder - .tx_data_store() - .insert_backrun_bundle(bundle_a) - .expect("Failed to insert bundle A"); + rbuilder.tx_data_store().insert_backrun_bundle(bundle_b).expect("Failed to insert bundle B"); + rbuilder.tx_data_store().insert_backrun_bundle(bundle_a).expect("Failed to insert bundle A"); // 5. Build the block driver.build_new_block().await?; @@ -242,26 +227,11 @@ async fn backrun_bundles_sorted_by_total_fee(rbuilder: LocalInstance) -> eyre::R let tx_hashes: Vec<_> = block.transactions.hashes().collect(); // All txs should be in block - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx not included in block" - ); - assert!( - tx_hashes.contains(&bundle_a_tx1_hash), - "Bundle A tx1 not included in block" - ); - assert!( - tx_hashes.contains(&bundle_a_tx2_hash), - "Bundle A tx2 not included in block" - ); - assert!( - tx_hashes.contains(&bundle_b_tx1_hash), - "Bundle B tx1 not included in block" - ); - assert!( - tx_hashes.contains(&bundle_b_tx2_hash), - "Bundle B tx2 not included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx not included in block"); + assert!(tx_hashes.contains(&bundle_a_tx1_hash), "Bundle A tx1 not included in block"); + assert!(tx_hashes.contains(&bundle_a_tx2_hash), "Bundle A tx2 not included in block"); + assert!(tx_hashes.contains(&bundle_b_tx1_hash), "Bundle B tx1 not included in block"); + assert!(tx_hashes.contains(&bundle_b_tx2_hash), "Bundle B tx2 not included in block"); // 7. Verify ordering: Bundle A txs come BEFORE Bundle B txs // (higher total fee bundle processed first) @@ -314,9 +284,7 @@ async fn backrun_bundle_rejected_low_total_fee(rbuilder: LocalInstance) -> eyre: // Send to mempool manually let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; // 2. Create backrun transactions with LOW total fee: // - backrun_1: priority fee 30 @@ -378,10 +346,7 @@ async fn backrun_bundle_rejected_low_total_fee(rbuilder: LocalInstance) -> eyre: let tx_hashes: Vec<_> = block.transactions.hashes().collect(); // Target tx SHOULD be in block (it was in mempool independently) - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx should be included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx should be included in block"); // backrun_1 should NOT be in block (bundle rejected: total fee 50 < target fee 100) assert!( @@ -390,10 +355,7 @@ async fn backrun_bundle_rejected_low_total_fee(rbuilder: LocalInstance) -> eyre: ); // backrun_2 should NOT be in block (bundle rejected) - assert!( - !tx_hashes.contains(&backrun_2_hash), - "backrun_2 should NOT be in block" - ); + assert!(!tx_hashes.contains(&backrun_2_hash), "backrun_2 should NOT be in block"); Ok(()) } @@ -406,10 +368,7 @@ async fn backrun_bundle_rejected_exceeds_gas_limit(rbuilder: LocalInstance) -> e // Set gas limit high enough for builder tx + target tx, but not backrun // Flashblocks has additional overhead, so use higher limits // Set limit to 500k, backrun requests 1M -> rejected - driver - .provider() - .raw_request::<(u64,), bool>("miner_setGasLimit".into(), (500_000,)) - .await?; + driver.provider().raw_request::<(u64,), bool>("miner_setGasLimit".into(), (500_000,)).await?; let target_tx = driver .create_transaction() @@ -420,9 +379,7 @@ async fn backrun_bundle_rejected_exceeds_gas_limit(rbuilder: LocalInstance) -> e let target_tx_hash = target_tx.tx_hash().clone(); let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; let backrun = driver .create_transaction() @@ -469,10 +426,7 @@ async fn backrun_bundle_rejected_exceeds_gas_limit(rbuilder: LocalInstance) -> e let block = driver.latest_full().await?; let tx_hashes: Vec<_> = block.transactions.hashes().collect(); - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx should be included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx should be included in block"); assert!( !tx_hashes.contains(&backrun_hash), @@ -504,9 +458,7 @@ async fn backrun_bundle_rejected_exceeds_da_limit(rbuilder: LocalInstance) -> ey let target_tx_hash = target_tx.tx_hash().clone(); let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; // Create backrun with large calldata to exceed DA limit let backrun = driver @@ -554,10 +506,7 @@ async fn backrun_bundle_rejected_exceeds_da_limit(rbuilder: LocalInstance) -> ey let block = driver.latest_full().await?; let tx_hashes: Vec<_> = block.transactions.hashes().collect(); - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx should be included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx should be included in block"); assert!( !tx_hashes.contains(&backrun_hash), @@ -582,9 +531,7 @@ async fn backrun_bundle_invalid_tx_skipped(rbuilder: LocalInstance) -> eyre::Res let target_tx_hash = target_tx.tx_hash().clone(); let provider = rbuilder.provider().await?; - let _ = provider - .send_raw_transaction(target_tx.encoded_2718().as_slice()) - .await?; + let _ = provider.send_raw_transaction(target_tx.encoded_2718().as_slice()).await?; let backrun_tx = driver .create_transaction() @@ -641,15 +588,9 @@ async fn backrun_bundle_invalid_tx_skipped(rbuilder: LocalInstance) -> eyre::Res let block = driver.latest_full().await?; let tx_hashes: Vec<_> = block.transactions.hashes().collect(); - assert!( - tx_hashes.contains(&target_tx_hash), - "Target tx should be included in block" - ); + assert!(tx_hashes.contains(&target_tx_hash), "Target tx should be included in block"); - assert!( - tx_hashes.contains(&conflicting_tx_hash), - "Conflicting tx should be included in block" - ); + assert!(tx_hashes.contains(&conflicting_tx_hash), "Conflicting tx should be included in block"); assert!( !tx_hashes.contains(&backrun_tx_hash), diff --git a/crates/builder/op-rbuilder/src/tests/data_availability.rs b/crates/builder/op-rbuilder/src/tests/data_availability.rs index 9621f398..26c30f3d 100644 --- a/crates/builder/op-rbuilder/src/tests/data_availability.rs +++ b/crates/builder/op-rbuilder/src/tests/data_availability.rs @@ -1,7 +1,8 @@ -use crate::tests::{BlockTransactionsExt, ChainDriverExt, LocalInstance, TransactionBuilderExt}; use alloy_provider::Provider; use macros::{if_flashblocks, if_standard, rb_test}; +use crate::tests::{BlockTransactionsExt, ChainDriverExt, LocalInstance, TransactionBuilderExt}; + /// This test ensures that the transaction size limit is respected. /// We will set limit to 1 byte and see that the builder will not include any transactions. #[rb_test] @@ -15,18 +16,11 @@ async fn tx_size_limit(rbuilder: LocalInstance) -> eyre::Result<()> { .await?; assert!(call, "miner_setMaxDASize should be executed successfully"); - let unfit_tx = driver - .create_transaction() - .with_max_priority_fee_per_gas(50) - .send() - .await?; + let unfit_tx = driver.create_transaction().with_max_priority_fee_per_gas(50).send().await?; let block = driver.build_new_block().await?; // tx should not be included because we set the tx_size_limit to 1 - assert!( - !block.includes(unfit_tx.tx_hash()), - "transaction should not be included in the block" - ); + assert!(!block.includes(unfit_tx.tx_hash()), "transaction should not be included in the block"); Ok(()) } @@ -47,10 +41,7 @@ async fn block_size_limit(rbuilder: LocalInstance) -> eyre::Result<()> { let (unfit_tx, block) = driver.build_new_block_with_valid_transaction().await?; // tx should not be included because we set the tx_size_limit to 1 - assert!( - !block.includes(&unfit_tx), - "transaction should not be included in the block" - ); + assert!(!block.includes(&unfit_tx), "transaction should not be included in the block"); Ok(()) } @@ -72,21 +63,9 @@ async fn block_fill(rbuilder: LocalInstance) -> eyre::Result<()> { // We already have 2 so we will spawn one more to check that it won't be included (it won't fit // because of builder tx) - let fit_tx_1 = driver - .create_transaction() - .with_max_priority_fee_per_gas(50) - .send() - .await?; - let fit_tx_2 = driver - .create_transaction() - .with_max_priority_fee_per_gas(50) - .send() - .await?; - let fit_tx_3 = driver - .create_transaction() - .with_max_priority_fee_per_gas(50) - .send() - .await?; + let fit_tx_1 = driver.create_transaction().with_max_priority_fee_per_gas(50).send().await?; + let fit_tx_2 = driver.create_transaction().with_max_priority_fee_per_gas(50).send().await?; + let fit_tx_3 = driver.create_transaction().with_max_priority_fee_per_gas(50).send().await?; let unfit_tx_4 = driver.create_transaction().send().await?; let block = driver.build_new_block_with_current_timestamp(None).await?; @@ -107,10 +86,7 @@ async fn block_fill(rbuilder: LocalInstance) -> eyre::Result<()> { assert!(!block.includes(fit_tx_3.tx_hash()), "tx should not be in block"); } - assert!( - !block.includes(unfit_tx_4.tx_hash()), - "unfit tx should not be in block" - ); + assert!(!block.includes(unfit_tx_4.tx_hash()), "unfit tx should not be in block"); assert!( driver.latest_full().await?.transactions.len() == 5, "builder + deposit + 3 valid txs should be in the block" @@ -160,10 +136,7 @@ async fn da_footprint_fills_to_limit(rbuilder: LocalInstance) -> eyre::Result<() let block = driver.build_new_block_with_current_timestamp(None).await?; // Verify that blob_gas_used (DA footprint) is set and respects limits - assert!( - block.header.blob_gas_used.is_some(), - "blob_gas_used should be set in Jovian" - ); + assert!(block.header.blob_gas_used.is_some(), "blob_gas_used should be set in Jovian"); let blob_gas = block.header.blob_gas_used.unwrap(); diff --git a/crates/builder/op-rbuilder/src/tests/flashblocks.rs b/crates/builder/op-rbuilder/src/tests/flashblocks.rs index c60e9d5a..cd93f679 100644 --- a/crates/builder/op-rbuilder/src/tests/flashblocks.rs +++ b/crates/builder/op-rbuilder/src/tests/flashblocks.rs @@ -1,10 +1,11 @@ +use std::time::Duration; + use alloy_consensus::Transaction; use alloy_eips::Decodable2718; use alloy_primitives::{Address, TxHash, U256}; use alloy_provider::Provider; use macros::rb_test; use op_alloy_consensus::OpTxEnvelope; -use std::time::Duration; use crate::{ args::{FlashblocksArgs, OpRbuilderArgs}, @@ -35,11 +36,7 @@ async fn smoke_dynamic_base(rbuilder: LocalInstance) -> eyre::Result<()> { for _ in 0..10 { for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } let block = driver.build_new_block_with_current_timestamp(None).await?; assert_eq!(block.transactions.len(), 8, "Got: {:?}", block.transactions); // 5 normal txn + deposit + 2 builder txn @@ -73,11 +70,7 @@ async fn smoke_dynamic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> { for _ in 0..10 { for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } let block = driver.build_new_block_with_current_timestamp(None).await?; assert_eq!(block.transactions.len(), 8, "Got: {:?}", block.transactions); // 5 normal txn + deposit + 2 builder txn @@ -111,11 +104,7 @@ async fn smoke_classic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> { for _ in 0..10 { for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } let block = driver.build_new_block().await?; assert_eq!(block.transactions.len(), 8, "Got: {:?}", block.transactions); // 5 normal txn + deposit + 2 builder txn @@ -149,11 +138,7 @@ async fn smoke_classic_base(rbuilder: LocalInstance) -> eyre::Result<()> { for _ in 0..10 { for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } let block = driver.build_new_block().await?; assert_eq!(block.transactions.len(), 8, "Got: {:?}", block.transactions); // 5 normal txn + deposit + 2 builder txn @@ -187,21 +172,12 @@ async fn unichain_dynamic_with_lag(rbuilder: LocalInstance) -> eyre::Result<()> for i in 0..9 { for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } let block = driver .build_new_block_with_current_timestamp(Some(Duration::from_millis(i * 100))) .await?; - assert_eq!( - block.transactions.len(), - 8, - "Got: {:#?}", - block.transactions - ); // 5 normal txn + deposit + 2 builder txn + assert_eq!(block.transactions.len(), 8, "Got: {:#?}", block.transactions); // 5 normal txn + deposit + 2 builder txn tokio::time::sleep(std::time::Duration::from_secs(1)).await; } @@ -230,15 +206,10 @@ async fn dynamic_with_full_block_lag(rbuilder: LocalInstance) -> eyre::Result<() for _ in 0..5 { // send a valid transaction - let _ = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _ = driver.create_transaction().random_valid_transfer().send().await?; } - let block = driver - .build_new_block_with_current_timestamp(Some(Duration::from_millis(999))) - .await?; + let block = + driver.build_new_block_with_current_timestamp(Some(Duration::from_millis(999))).await?; // We could only produce block with deposits + builder tx because of short time frame assert_eq!(block.transactions.len(), 2); @@ -290,17 +261,10 @@ async fn test_flashblock_min_filtering(rbuilder: LocalInstance) -> eyre::Result< // Check that tx1 comes before tx2 let tx1_hash = *tx1.tx_hash(); let tx2_hash = *tx2.tx_hash(); - let tx1_pos = flashblocks_listener - .find_transaction_flashblock(&tx1_hash) - .unwrap(); - let tx2_pos = flashblocks_listener - .find_transaction_flashblock(&tx2_hash) - .unwrap(); - - assert!( - tx1_pos < tx2_pos, - "tx {tx1_hash:?} does not come before {tx2_hash:?}" - ); + let tx1_pos = flashblocks_listener.find_transaction_flashblock(&tx1_hash).unwrap(); + let tx2_pos = flashblocks_listener.find_transaction_flashblock(&tx2_hash).unwrap(); + + assert!(tx1_pos < tx2_pos, "tx {tx1_hash:?} does not come before {tx2_hash:?}"); let flashblocks = flashblocks_listener.get_flashblocks(); assert_eq!(6, flashblocks.len()); @@ -337,11 +301,7 @@ async fn test_flashblock_max_filtering(rbuilder: LocalInstance) -> eyre::Result< .await?; assert!(call, "miner_setMaxDASize should be executed successfully"); - let _fit_tx_1 = driver - .create_transaction() - .with_max_priority_fee_per_gas(50) - .send() - .await?; + let _fit_tx_1 = driver.create_transaction().with_max_priority_fee_per_gas(50).send().await?; let tx1 = driver .create_transaction() @@ -352,11 +312,7 @@ async fn test_flashblock_max_filtering(rbuilder: LocalInstance) -> eyre::Result< let block = driver.build_new_block_with_current_timestamp(None).await?; assert!(!block.includes(tx1.tx_hash())); - assert!( - flashblocks_listener - .find_transaction_flashblock(tx1.tx_hash()) - .is_none() - ); + assert!(flashblocks_listener.find_transaction_flashblock(tx1.tx_hash()).is_none()); let flashblocks = flashblocks_listener.get_flashblocks(); assert_eq!(6, flashblocks.len()); @@ -386,9 +342,7 @@ async fn test_flashblock_min_max_filtering(rbuilder: LocalInstance) -> eyre::Res .create_transaction() .random_valid_transfer() .with_bundle( - BundleOpts::default() - .with_flashblock_number_max(2) - .with_flashblock_number_min(2), + BundleOpts::default().with_flashblock_number_max(2).with_flashblock_number_min(2), ) .send() .await?; @@ -398,9 +352,7 @@ async fn test_flashblock_min_max_filtering(rbuilder: LocalInstance) -> eyre::Res // It ends up in the 2nd flashblock assert_eq!( 2, - flashblocks_listener - .find_transaction_flashblock(tx1.tx_hash()) - .unwrap(), + flashblocks_listener.find_transaction_flashblock(tx1.tx_hash()).unwrap(), "Transaction should be in the 2nd flashblock" ); @@ -430,20 +382,13 @@ async fn test_flashblocks_no_state_root_calculation(rbuilder: LocalInstance) -> let driver = rbuilder.driver().await?; // Send a transaction to ensure block has some activity - let _tx = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let _tx = driver.create_transaction().random_valid_transfer().send().await?; // Build a block with current timestamp (not historical) and disable_state_root: true let block = driver.build_new_block_with_current_timestamp(None).await?; // Verify that flashblocks are still produced (block should have transactions) - assert!( - block.transactions.len() > 2, - "Block should contain transactions" - ); // deposit + builder tx + user tx + assert!(block.transactions.len() > 2, "Block should contain transactions"); // deposit + builder tx + user tx // Verify that state root is not calculated (should be zero) assert_eq!( @@ -499,10 +444,7 @@ async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> // Verify first block structure assert_eq!(block.transactions.len(), 10); - let txs = block - .transactions - .as_transactions() - .expect("transactions not in block"); + let txs = block.transactions.as_transactions().expect("transactions not in block"); // Verify builder txs (should be regular since builder tx is not registered yet) verify_builder_txs( @@ -533,10 +475,7 @@ async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> // Mine initialization driver.build_new_block_with_current_timestamp(None).await?; - provider - .get_transaction_receipt(*init_tx.tx_hash()) - .await? - .expect("init tx not mined"); + provider.get_transaction_receipt(*init_tx.tx_hash()).await?.expect("init tx not mined"); // Create user transactions for flashblocks 1 - 5 let user_transactions = create_flashblock_transactions(&driver, 1..5).await?; @@ -545,17 +484,10 @@ async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> // with builder registered let block = driver.build_new_block_with_current_timestamp(None).await?; assert_eq!(block.transactions.len(), 10); - let txs = block - .transactions - .as_transactions() - .expect("transactions not in block"); + let txs = block.transactions.as_transactions().expect("transactions not in block"); // Fallback block should have regular builder tx after deposit tx - assert_eq!( - txs[1].to(), - Some(Address::ZERO), - "Fallback block should have regular builder tx" - ); + assert_eq!(txs[1].to(), Some(Address::ZERO), "Fallback block should have regular builder tx"); // Other builder txs should call the contract verify_builder_txs( @@ -571,11 +503,7 @@ async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> // Verify flashblock number incremented correctly let contract = FlashblocksNumber::new(contract_address, provider.clone()); let current_number = contract.getFlashblockNumber().call().await?; - assert_eq!( - current_number, - U256::from(7), - "Flashblock number not incremented correctly" - ); + assert_eq!(current_number, U256::from(7), "Flashblock number not incremented correctly"); // Verify flashblocks let flashblocks = flashblocks_listener.get_flashblocks(); @@ -588,18 +516,16 @@ async fn test_flashblocks_number_contract_builder_tx(rbuilder: LocalInstance) -> let is_fallback = i % 5 == 0; let tx_index = if is_fallback { 1 } else { 0 }; - let tx_bytes = flashblock.diff.transactions.get(tx_index).expect(&format!( - "Flashblock {} should have tx at index {}", - i, tx_index - )); + let tx_bytes = flashblock + .diff + .transactions + .get(tx_index) + .expect(&format!("Flashblock {} should have tx at index {}", i, tx_index)); let tx = OpTxEnvelope::decode_2718(&mut tx_bytes.as_ref()) .expect("failed to decode transaction"); - let expected_to = if i < 7 || i == 10 { - Some(Address::ZERO) - } else { - Some(contract_address) - }; + let expected_to = + if i < 7 || i == 10 { Some(Address::ZERO) } else { Some(contract_address) }; assert_eq!( tx.to(), diff --git a/crates/builder/op-rbuilder/src/tests/flashtestations.rs b/crates/builder/op-rbuilder/src/tests/flashtestations.rs index 002ce5cf..3bce19f0 100644 --- a/crates/builder/op-rbuilder/src/tests/flashtestations.rs +++ b/crates/builder/op-rbuilder/src/tests/flashtestations.rs @@ -37,14 +37,8 @@ async fn test_flashtestations_invalid_quote(rbuilder: LocalInstance) -> eyre::Re setup_flashtestation_contracts(&driver, &provider, false, false).await?; // verify not registered let contract = FlashtestationRegistry::new(FLASHTESTATION_REGISTRY_ADDRESS, provider.clone()); - let result = contract - .getRegistrationStatus(TEE_DEBUG_ADDRESS) - .call() - .await?; - assert!( - !result.isValid, - "The tee key is registered for invalid quote" - ); + let result = contract.getRegistrationStatus(TEE_DEBUG_ADDRESS).call().await?; + assert!(!result.isValid, "The tee key is registered for invalid quote"); // check that only regular builder tx is in the block let (tx_hash, block) = driver.build_new_block_with_valid_transaction().await?; let txs = block.transactions.into_transactions_vec(); @@ -63,17 +57,9 @@ async fn test_flashtestations_invalid_quote(rbuilder: LocalInstance) -> eyre::Re ); let last_txs = &txs[txs.len() - 2..]; // Check user transaction - assert_eq!( - last_txs[0].inner.tx_hash(), - tx_hash, - "tx hash for user transaction should match" - ); + assert_eq!(last_txs[0].inner.tx_hash(), tx_hash, "tx hash for user transaction should match"); // Check builder tx - assert_eq!( - last_txs[1].to(), - Some(Address::ZERO), - "builder tx should send to zero address" - ); + assert_eq!(last_txs[1].to(), Some(Address::ZERO), "builder tx should send to zero address"); Ok(()) } @@ -111,17 +97,9 @@ async fn test_flashtestations_unauthorized_workload(rbuilder: LocalInstance) -> ); let last_txs = &txs[txs.len() - 2..]; // Check user transaction - assert_eq!( - last_txs[0].inner.tx_hash(), - tx_hash, - "tx hash for user transaction should match" - ); + assert_eq!(last_txs[0].inner.tx_hash(), tx_hash, "tx hash for user transaction should match"); // Check builder tx - assert_eq!( - last_txs[1].to(), - Some(Address::ZERO), - "builder tx should send to zero address" - ); + assert_eq!(last_txs[1].to(), Some(Address::ZERO), "builder tx should send to zero address"); Ok(()) } @@ -158,11 +136,7 @@ async fn test_flashtestations_with_number_contract(rbuilder: LocalInstance) -> e let txs = block.transactions.into_transactions_vec(); assert_eq!(txs.len(), 8, "Expected 8 transactions in block"); // Check builder tx - assert_eq!( - txs[1].to(), - Some(Address::ZERO), - "fallback builder tx should send to zero address" - ); + assert_eq!(txs[1].to(), Some(Address::ZERO), "fallback builder tx should send to zero address"); // flashblocks number contract for i in 2..6 { assert_eq!( @@ -173,11 +147,7 @@ async fn test_flashtestations_with_number_contract(rbuilder: LocalInstance) -> e ); } // check regular tx - assert_eq!( - txs[6].tx_hash(), - *tx.tx_hash(), - "bundle tx was not in block" - ); + assert_eq!(txs[6].tx_hash(), *tx.tx_hash(), "bundle tx was not in block"); // check block proof tx assert_eq!( txs[7].to(), @@ -255,11 +225,7 @@ async fn test_flashtestations_permit_block_proof(rbuilder: LocalInstance) -> eyr ); let last_2_txs = &block.transactions.into_transactions_vec()[num_txs - 2..]; // Check builder tx - assert_eq!( - last_2_txs[0].to(), - Some(Address::ZERO), - "builder tx should send to zero address" - ); + assert_eq!(last_2_txs[0].to(), Some(Address::ZERO), "builder tx should send to zero address"); // check builder proof assert_eq!( last_2_txs[1].to(), @@ -316,11 +282,7 @@ async fn test_flashtestations_permit_with_flashblocks_number_contract( // // 1 deposit tx, 1 regular builder tx, 4 flashblocks number tx, 1 user tx, 1 block proof tx assert_eq!(num_txs, 8, "Expected 8 transactions in block"); // Check builder tx - assert_eq!( - txs[1].to(), - Some(Address::ZERO), - "builder tx should send to zero address" - ); + assert_eq!(txs[1].to(), Some(Address::ZERO), "builder tx should send to zero address"); // flashblocks number contract for i in 2..6 { assert_eq!( @@ -331,11 +293,7 @@ async fn test_flashtestations_permit_with_flashblocks_number_contract( ); } // user tx - assert_eq!( - txs[6].tx_hash(), - *tx.tx_hash(), - "user tx should be in correct position in block" - ); + assert_eq!(txs[6].tx_hash(), *tx.tx_hash(), "user tx should be in correct position in block"); assert_eq!( txs[7].to(), Some(BLOCK_BUILDER_POLICY_ADDRESS), @@ -449,11 +407,7 @@ async fn test_flashtestations_permit_with_flashblocks_number_permit( ); } // user tx - assert_eq!( - txs[6].tx_hash(), - *tx.tx_hash(), - "user tx should be in correct position in block" - ); + assert_eq!(txs[6].tx_hash(), *tx.tx_hash(), "user tx should be in correct position in block"); // check that the tee signer did not send any transactions let balance = provider.get_balance(TEE_DEBUG_ADDRESS).await?; assert!(balance.is_zero()); @@ -462,11 +416,7 @@ async fn test_flashtestations_permit_with_flashblocks_number_permit( // Verify flashblock number incremented correctly let contract = FlashblocksNumber::new(FLASHBLOCKS_NUMBER_ADDRESS, provider.clone()); let current_number = contract.getFlashblockNumber().call().await?; - assert_eq!( - current_number, - U256::from(4), - "Flashblock number not incremented correctly" - ); + assert_eq!(current_number, U256::from(4), "Flashblock number not incremented correctly"); Ok(()) } @@ -538,10 +488,7 @@ async fn setup_flashtestation_contracts( // verify registered let registry_contract = FlashtestationRegistry::new(FLASHTESTATION_REGISTRY_ADDRESS, provider.clone()); - let registration = registry_contract - .getRegistration(TEE_DEBUG_ADDRESS) - .call() - .await?; + let registration = registry_contract.getRegistration(TEE_DEBUG_ADDRESS).call().await?; assert!(registration._0, "The tee key is not registered"); } @@ -562,10 +509,7 @@ async fn setup_flashtestation_contracts( // verify workload id added let policy_contract = BlockBuilderPolicy::new(BLOCK_BUILDER_POLICY_ADDRESS, provider.clone()); - let is_allowed = policy_contract - .isAllowedPolicy(TEE_DEBUG_ADDRESS) - .call() - .await?; + let is_allowed = policy_contract.isAllowedPolicy(TEE_DEBUG_ADDRESS).call().await?; assert!(is_allowed.allowed, "The policy is not allowed") } @@ -578,14 +522,9 @@ async fn setup_flashtestation_contracts( .inner .contract_address .expect("contract receipt does not contain flashblock number contract address"); - assert_eq!( - mock_dcap_address, MOCK_DCAP_ADDRESS, - "mock dcap contract address mismatch" - ); + assert_eq!(mock_dcap_address, MOCK_DCAP_ADDRESS, "mock dcap contract address mismatch"); // verify flashtestations registry contract deployment - let receipt = provider - .get_transaction_receipt(*flashtestations_registry_tx.tx_hash()) - .await?; + let receipt = provider.get_transaction_receipt(*flashtestations_registry_tx.tx_hash()).await?; let flashtestations_registry_address = receipt .expect("flashtestations registry contract deployment not mined") .inner @@ -602,9 +541,7 @@ async fn setup_flashtestation_contracts( .expect("init registry tx not mined"); // verify block builder policy contract deployment - let receipt = provider - .get_transaction_receipt(*block_builder_policy_tx.tx_hash()) - .await?; + let receipt = provider.get_transaction_receipt(*block_builder_policy_tx.tx_hash()).await?; let block_builder_policy_address = receipt .expect("block builder policy contract deployment not mined") .inner @@ -661,10 +598,7 @@ async fn setup_flashblock_number_contract( ); // Verify initialization - provider - .get_transaction_receipt(*init_tx.tx_hash()) - .await? - .expect("init tx not mined"); + provider.get_transaction_receipt(*init_tx.tx_hash()).await?.expect("init tx not mined"); Ok(()) } diff --git a/crates/builder/op-rbuilder/src/tests/forks.rs b/crates/builder/op-rbuilder/src/tests/forks.rs index d136c375..3a1517c5 100644 --- a/crates/builder/op-rbuilder/src/tests/forks.rs +++ b/crates/builder/op-rbuilder/src/tests/forks.rs @@ -1,8 +1,10 @@ -use crate::tests::{BlockTransactionsExt, LocalInstance}; +use std::time::Duration; + use alloy_eips::{BlockNumberOrTag::Latest, Encodable2718, eip1559::MIN_PROTOCOL_BASE_FEE}; use alloy_primitives::bytes; use macros::{if_flashblocks, if_standard, rb_test}; -use std::time::Duration; + +use crate::tests::{BlockTransactionsExt, LocalInstance}; #[rb_test] async fn jovian_block_parameters_set(rbuilder: LocalInstance) -> eyre::Result<()> { @@ -32,10 +34,7 @@ async fn jovian_block_parameters_set(rbuilder: LocalInstance) -> eyre::Result<() assert_eq!(block.header.extra_data.slice(0..1), bytes!("0x01")); // Min Base Fee of zero by default - assert_eq!( - block.header.extra_data.slice(9..=16), - bytes!("0x0000000000000000"), - ); + assert_eq!(block.header.extra_data.slice(9..=16), bytes!("0x0000000000000000"),); Ok(()) } @@ -43,9 +42,8 @@ async fn jovian_block_parameters_set(rbuilder: LocalInstance) -> eyre::Result<() #[rb_test] async fn jovian_no_tx_pool_sync(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let block = driver - .build_new_block_with_txs_timestamp(vec![], Some(true), None, None, Some(0)) - .await?; + let block = + driver.build_new_block_with_txs_timestamp(vec![], Some(true), None, None, Some(0)).await?; // Deposit transaction + user transaction if_flashblocks! { @@ -88,10 +86,7 @@ async fn jovian_no_tx_pool_sync(rbuilder: LocalInstance) -> eyre::Result<()> { #[rb_test] async fn jovian_minimum_base_fee(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let genesis = driver - .get_block(Latest) - .await? - .expect("must have genesis block"); + let genesis = driver.get_block(Latest).await?.expect("must have genesis block"); assert_eq!(genesis.header.base_fee_per_gas, Some(1)); @@ -102,10 +97,7 @@ async fn jovian_minimum_base_fee(rbuilder: LocalInstance) -> eyre::Result<()> { .build_new_block_with_txs_timestamp(vec![], None, Some(block_timestamp), None, min_base_fee) .await?; - assert_eq!( - block_one.header.extra_data.slice(9..=16), - bytes!("0x000000000000000E"), - ); + assert_eq!(block_one.header.extra_data.slice(9..=16), bytes!("0x000000000000000E"),); let overpriced_tx = driver .create_transaction() @@ -123,10 +115,7 @@ async fn jovian_minimum_base_fee(rbuilder: LocalInstance) -> eyre::Result<()> { .build_new_block_with_txs_timestamp(vec![], None, Some(block_timestamp), None, min_base_fee) .await?; - assert_eq!( - block_two.header.extra_data.slice(9..=16), - bytes!("0x000000000000000E"), - ); + assert_eq!(block_two.header.extra_data.slice(9..=16), bytes!("0x000000000000000E"),); assert!(block_two.includes(overpriced_tx.tx_hash())); assert!(!block_two.includes(underpriced_tx.tx_hash())); @@ -137,10 +126,7 @@ async fn jovian_minimum_base_fee(rbuilder: LocalInstance) -> eyre::Result<()> { #[rb_test] async fn jovian_minimum_fee_must_be_set(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let genesis = driver - .get_block(Latest) - .await? - .expect("must have genesis block"); + let genesis = driver.get_block(Latest).await?.expect("must have genesis block"); let block_timestamp = Duration::from_secs(genesis.header.timestamp) + Duration::from_secs(1); let response = driver .build_new_block_with_txs_timestamp(vec![], None, Some(block_timestamp), None, None) diff --git a/crates/builder/op-rbuilder/src/tests/framework/apis.rs b/crates/builder/op-rbuilder/src/tests/framework/apis.rs index 1ff8111f..f2abf68c 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/apis.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/apis.rs @@ -1,9 +1,8 @@ -use super::DEFAULT_JWT_TOKEN; +use core::{future::Future, marker::PhantomData}; + use alloy_eips::{BlockNumberOrTag, eip7685::Requests}; use alloy_primitives::B256; - use alloy_rpc_types_engine::{ForkchoiceState, ForkchoiceUpdated, PayloadStatus}; -use core::{future::Future, marker::PhantomData}; use jsonrpsee::{ core::{RpcResult, client::SubscriptionClientT}, proc_macros::rpc, @@ -17,6 +16,8 @@ use reth_rpc_layer::{AuthClientLayer, JwtSecret}; use serde_json::Value; use tracing::debug; +use super::DEFAULT_JWT_TOKEN; + #[derive(Clone, Debug)] pub enum Address { Ipc(String), @@ -91,9 +92,7 @@ impl EngineApi { pub fn with_localhost_port(port: u16) -> EngineApi { EngineApi:: { address: Address::Http( - format!("http://localhost:{port}") - .parse() - .expect("Invalid URL"), + format!("http://localhost:{port}").parse().expect("Invalid URL"), ), jwt_secret: DEFAULT_JWT_TOKEN.parse().expect("Invalid JWT"), _tag: PhantomData, @@ -145,15 +144,9 @@ impl EngineApi

{ &self, payload_id: PayloadId, ) -> eyre::Result<::ExecutionPayloadEnvelopeV4> { - debug!( - "Fetching payload with id: {} at {}", - payload_id, - chrono::Utc::now() - ); - Ok( - OpEngineApiClient::::get_payload_v4(&self.client().await, payload_id) - .await?, - ) + debug!("Fetching payload with id: {} at {}", payload_id, chrono::Utc::now()); + Ok(OpEngineApiClient::::get_payload_v4(&self.client().await, payload_id) + .await?) } pub async fn new_payload( diff --git a/crates/builder/op-rbuilder/src/tests/framework/contracts.rs b/crates/builder/op-rbuilder/src/tests/framework/contracts.rs index 5f9b2449..bfc792ca 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/contracts.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/contracts.rs @@ -1,7 +1,8 @@ pub mod flashtestation_registry { - use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; use alloy_sol_types::sol; + use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; + sol!( // https://github.com/flashbots/flashtestations/tree/7cc7f68492fe672a823dd2dead649793aac1f216 #[sol(rpc, abi)] @@ -11,9 +12,10 @@ pub mod flashtestation_registry { } pub mod block_builder_policy { - use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; use alloy_sol_types::sol; + use crate::tests::framework::contracts::block_builder_policy::BlockBuilderPolicy::TD10ReportBody; + sol!( // https://github.com/flashbots/flashtestations/tree/7cc7f68492fe672a823dd2dead649793aac1f216 #[sol(rpc, abi)] diff --git a/crates/builder/op-rbuilder/src/tests/framework/driver.rs b/crates/builder/op-rbuilder/src/tests/framework/driver.rs index 39bae4c7..fa15dcd7 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/driver.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/driver.rs @@ -95,8 +95,7 @@ impl ChainDriver { // public test api impl ChainDriver { pub async fn build_new_block_with_no_tx_pool(&self) -> eyre::Result> { - self.build_new_block_with_txs_timestamp(vec![], Some(true), None, None, Some(0)) - .await + self.build_new_block_with_txs_timestamp(vec![], Some(true), None, None, Some(0)).await } /// Builds a new block using the current state of the chain and the transactions in the pool. @@ -109,8 +108,7 @@ impl ChainDriver { &self, timestamp_jitter: Option, ) -> eyre::Result> { - self.build_new_block_with_txs_timestamp(vec![], None, None, timestamp_jitter, Some(0)) - .await + self.build_new_block_with_txs_timestamp(vec![], None, None, timestamp_jitter, Some(0)).await } /// Builds a new block with provided txs and timestamp @@ -232,16 +230,12 @@ impl ChainDriver { let new_block_hash = payload.payload_inner.payload_inner.payload_inner.block_hash; - self.engine_api - .update_forkchoice(latest.header.hash, new_block_hash, None) - .await?; + self.engine_api.update_forkchoice(latest.header.hash, new_block_hash, None).await?; - let block = self - .provider - .get_block_by_number(BlockNumberOrTag::Latest) - .full() - .await? - .ok_or_else(|| eyre::eyre!("Failed to get latest block after building new block"))?; + let block = + self.provider.get_block_by_number(BlockNumberOrTag::Latest).full().await?.ok_or_else( + || eyre::eyre!("Failed to get latest block after building new block"), + )?; assert_eq!( block.header.hash, new_block_hash, @@ -325,10 +319,7 @@ impl ChainDriver { impl ChainDriver { async fn fcu(&self, attribs: OpPayloadAttributes) -> eyre::Result { let latest = self.latest().await?.header.hash; - let response = self - .engine_api - .update_forkchoice(latest, latest, Some(attribs)) - .await?; + let response = self.engine_api.update_forkchoice(latest, latest, Some(attribs)).await?; Ok(response) } diff --git a/crates/builder/op-rbuilder/src/tests/framework/external.rs b/crates/builder/op-rbuilder/src/tests/framework/external.rs index 8bb99eda..66092ded 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/external.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/external.rs @@ -1,3 +1,5 @@ +use std::path::{Path, PathBuf}; + use alloy_consensus::constants::EMPTY_WITHDRAWALS; use alloy_eips::{BlockNumberOrTag, Encodable2718, eip7685::Requests}; use alloy_primitives::{B256, U256, keccak256, private::alloy_rlp::Encodable}; @@ -8,7 +10,6 @@ use alloy_rpc_types_engine::{ use futures::{StreamExt, TryStreamExt}; use op_alloy_network::Optimism; use op_alloy_rpc_types_engine::OpExecutionPayloadV4; -use std::path::{Path, PathBuf}; use testcontainers::bollard::{ Docker, container::{ @@ -61,18 +62,13 @@ impl ExternalNode { std::fs::create_dir_all(&tempdir) .map_err(|_| eyre::eyre!("Failed to create temporary directory"))?; - std::fs::write( - tempdir.join("genesis.json"), - include_str!("./artifacts/genesis.json.tmpl"), - ) - .map_err(|_| eyre::eyre!("Failed to write genesis file"))?; + std::fs::write(tempdir.join("genesis.json"), include_str!("./artifacts/genesis.json.tmpl")) + .map_err(|_| eyre::eyre!("Failed to write genesis file"))?; // Create Docker container with reth EL client let container = create_container(&tempdir, &docker, version_tag).await?; - docker - .start_container(&container.id, None::>) - .await?; + docker.start_container(&container.id, None::>).await?; // Wait for the container to be ready and IPCs to be created await_ipc_readiness(&docker, &container.id).await?; @@ -101,13 +97,7 @@ impl ExternalNode { } }); - Ok(Self { - engine_api, - provider, - docker, - tempdir, - container_id: container.id, - }) + Ok(Self { engine_api, provider, docker, tempdir, container_id: container.id }) } /// Creates a new instance of `ExternalNode` that runs the `op-reth` client in a Docker container @@ -180,9 +170,7 @@ impl ExternalNode { let mut our_current_height = our_latest_number + 1; while our_current_height <= latest_number { - let payload = chain - .execution_payload_for_block(our_current_height) - .await?; + let payload = chain.execution_payload_for_block(our_current_height).await?; let (latest_hash, _) = self.provider().latest_block_hash_and_number().await?; @@ -199,9 +187,7 @@ impl ExternalNode { } let new_chain_hash = status.latest_valid_hash.unwrap_or_default(); - self.engine_api() - .update_forkchoice(latest_hash, new_chain_hash, None) - .await?; + self.engine_api().update_forkchoice(latest_hash, new_chain_hash, None).await?; our_current_height += 1; } @@ -244,9 +230,7 @@ impl ExternalNode { let (latest_hash, _) = self.provider.latest_block_hash_and_number().await?; - self.engine_api - .update_forkchoice(latest_hash, new_block_hash, None) - .await?; + self.engine_api.update_forkchoice(latest_hash, new_block_hash, None).await?; Ok(()) } @@ -270,10 +254,7 @@ async fn create_container( version_tag: &str, ) -> eyre::Result { let host_config = HostConfig { - binds: Some(vec![format!( - "{}:/home/op-reth-shared:rw", - tempdir.display() - )]), + binds: Some(vec![format!("{}:/home/op-reth-shared:rw", tempdir.display())]), ..Default::default() }; @@ -289,10 +270,7 @@ async fn create_container( ); while let Some(pull_result) = pull_stream.try_next().await? { - debug!( - "Pulling 'ghcr.io/paradigmxyz/op-reth:{version_tag}' locally: {:?}", - pull_result - ); + debug!("Pulling 'ghcr.io/paradigmxyz/op-reth:{version_tag}' locally: {:?}", pull_result); } // Don't expose any ports, as we will only use IPC for communication. @@ -321,10 +299,7 @@ async fn create_container( }; Ok(docker - .create_container( - Some(CreateContainerOptions::::default()), - container_config, - ) + .create_container(Some(CreateContainerOptions::::default()), container_config) .await?) } @@ -406,9 +381,7 @@ async fn await_ipc_readiness(docker: &Docker, container: &str) -> eyre::Result<( } if !auth_ipc_started || !rpc_ipc_started { - return Err(eyre::eyre!( - "Failed to start op-reth container: IPCs not ready" - )); + return Err(eyre::eyre!("Failed to start op-reth container: IPCs not ready")); } Ok(()) @@ -417,30 +390,21 @@ async fn await_ipc_readiness(docker: &Docker, container: &str) -> eyre::Result<( async fn cleanup(tempdir: PathBuf, docker: Docker, container_id: String) { // This is a no-op function that will be spawned to clean up the container on ctrl-c // or Drop. - debug!( - "Cleaning up external node resources at {} [{container_id}]...", - tempdir.display() - ); + debug!("Cleaning up external node resources at {} [{container_id}]...", tempdir.display()); if !tempdir.exists() { return; // If the tempdir does not exist, there's nothing to clean up. } // Block on cleaning up the container - if let Err(e) = docker - .stop_container(&container_id, None::) - .await - { + if let Err(e) = docker.stop_container(&container_id, None::).await { warn!("Failed to stop container {}: {}", container_id, e); } if let Err(e) = docker .remove_container( &container_id, - Some(RemoveContainerOptions { - force: true, - ..Default::default() - }), + Some(RemoveContainerOptions { force: true, ..Default::default() }), ) .await { diff --git a/crates/builder/op-rbuilder/src/tests/framework/instance.rs b/crates/builder/op-rbuilder/src/tests/framework/instance.rs index 3c39cc51..73d9950f 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/instance.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/instance.rs @@ -1,21 +1,3 @@ -use crate::{ - args::OpRbuilderArgs, - builders::{BuilderConfig, FlashblocksBuilder, PayloadBuilder, StandardBuilder}, - primitives::reth::engine_api_builder::OpEngineApiBuilder, - revert_protection::{EthApiExtServer, RevertProtectionExt}, - tests::{ - EngineApi, Ipc, TEE_DEBUG_ADDRESS, TransactionPoolObserver, builder_signer, create_test_db, - framework::driver::ChainDriver, get_available_port, - }, - tx::FBPooledTransaction, - tx_data_store::TxDataStore, - tx_signer::Signer, -}; -use alloy_primitives::{Address, B256, Bytes, hex, keccak256}; -use alloy_provider::{Identity, ProviderBuilder, RootProvider}; -use clap::Parser; -use reth_node_core::{args::{DatadirArgs, NetworkArgs, RpcServerArgs}, exit::NodeExitFuture}; -use reth_tasks::TaskManager; use core::{ any::Any, future::Future, @@ -24,6 +6,15 @@ use core::{ task::{Context, Poll}, time::Duration, }; +use std::{ + net::SocketAddr, + sync::{Arc, LazyLock}, +}; + +use alloy_primitives::{Address, B256, Bytes, hex, keccak256}; +use alloy_provider::{Identity, ProviderBuilder, RootProvider}; +use base_flashtypes::FlashblocksPayloadV1; +use clap::Parser; use futures::{FutureExt, StreamExt}; use http::{Request, Response, StatusCode}; use http_body_util::Full; @@ -34,6 +25,10 @@ use nanoid::nanoid; use op_alloy_network::Optimism; use parking_lot::Mutex; use reth_node_builder::{NodeBuilder, NodeConfig}; +use reth_node_core::{ + args::{DatadirArgs, NetworkArgs, RpcServerArgs}, + exit::NodeExitFuture, +}; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_cli::commands::Commands; use reth_optimism_node::{ @@ -41,16 +36,26 @@ use reth_optimism_node::{ node::{OpAddOns, OpAddOnsBuilder, OpEngineValidatorBuilder, OpPoolBuilder}, }; use reth_optimism_rpc::OpEthApiBuilder; +use reth_tasks::TaskManager; use reth_transaction_pool::{AllTransactionsEvents, TransactionPool}; -use base_flashtypes::FlashblocksPayloadV1; -use std::{ - net::SocketAddr, - sync::{Arc, LazyLock}, -}; use tokio::{net::TcpListener, sync::oneshot, task::JoinHandle}; use tokio_tungstenite::{connect_async, tungstenite::Message}; use tokio_util::sync::CancellationToken; +use crate::{ + args::OpRbuilderArgs, + builders::{BuilderConfig, FlashblocksBuilder, PayloadBuilder, StandardBuilder}, + primitives::reth::engine_api_builder::OpEngineApiBuilder, + revert_protection::{EthApiExtServer, RevertProtectionExt}, + tests::{ + EngineApi, Ipc, TEE_DEBUG_ADDRESS, TransactionPoolObserver, builder_signer, create_test_db, + framework::driver::ChainDriver, get_available_port, + }, + tx::FBPooledTransaction, + tx_data_store::TxDataStore, + tx_signer::Signer, +}; + /// Clears OTEL-related environment variables that can interfere with CLI argument parsing. /// This is necessary because clap reads env vars for args with `env = "..."` attributes, /// and external OTEL env vars (e.g., `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`) may contain @@ -168,8 +173,7 @@ impl LocalInstance { reverted_cache, ); - ctx.modules - .add_or_replace_configured(revert_protection_ext.into_rpc())?; + ctx.modules.add_or_replace_configured(revert_protection_ext.into_rpc())?; } Ok(()) @@ -193,9 +197,7 @@ impl LocalInstance { // Wait for all required components to be ready rpc_ready_rx.await.expect("Failed to receive ready signal"); - let pool_monitor = txpool_ready_rx - .await - .expect("Failed to receive txpool ready signal"); + let pool_monitor = txpool_ready_rx.await.expect("Failed to receive txpool ready signal"); Ok(Self { args, @@ -215,9 +217,7 @@ impl LocalInstance { pub async fn standard() -> eyre::Result { clear_otel_env_vars(); let args = crate::args::Cli::parse_from(["dummy", "node"]); - let Commands::Node(ref node_command) = args.command else { - unreachable!() - }; + let Commands::Node(ref node_command) = args.command else { unreachable!() }; Self::new::(node_command.ext.clone()).await } @@ -226,9 +226,7 @@ impl LocalInstance { pub async fn flashblocks() -> eyre::Result { clear_otel_env_vars(); let mut args = crate::args::Cli::parse_from(["dummy", "node"]); - let Commands::Node(ref mut node_command) = args.command else { - unreachable!() - }; + let Commands::Node(ref mut node_command) = args.command else { unreachable!() }; node_command.ext.flashblocks.enabled = true; node_command.ext.flashblocks.flashblocks_port = 0; // use random os assigned port Self::new::(node_command.ext.clone()).await @@ -254,11 +252,7 @@ impl LocalInstance { .parse() .expect("Failed to parse flashblocks IP address"); - let ipaddr = if ipaddr.is_unspecified() { - Ipv4Addr::LOCALHOST - } else { - ipaddr - }; + let ipaddr = if ipaddr.is_unspecified() { Ipv4Addr::LOCALHOST } else { ipaddr }; let port = self.args.flashblocks.flashblocks_port; @@ -310,10 +304,7 @@ impl Drop for LocalInstance { if let Some(task_manager) = self.task_manager.take() { task_manager.graceful_shutdown_with_timeout(Duration::from_secs(3)); std::fs::remove_dir_all(self.config().datadir().to_string()).unwrap_or_else(|e| { - panic!( - "Failed to remove temporary data directory {}: {e}", - self.config().datadir() - ) + panic!("Failed to remove temporary data directory {}: {e}", self.config().datadir()) }); } } @@ -331,19 +322,13 @@ pub fn default_node_config() -> NodeConfig { let tempdir = std::env::temp_dir(); let random_id = nanoid!(); - let data_path = tempdir - .join(format!("rbuilder.{random_id}.datadir")) - .to_path_buf(); + let data_path = tempdir.join(format!("rbuilder.{random_id}.datadir")).to_path_buf(); std::fs::create_dir_all(&data_path).expect("Failed to create temporary data directory"); - let rpc_ipc_path = tempdir - .join(format!("rbuilder.{random_id}.rpc-ipc")) - .to_path_buf(); + let rpc_ipc_path = tempdir.join(format!("rbuilder.{random_id}.rpc-ipc")).to_path_buf(); - let auth_ipc_path = tempdir - .join(format!("rbuilder.{random_id}.auth-ipc")) - .to_path_buf(); + let auth_ipc_path = tempdir.join(format!("rbuilder.{random_id}.auth-ipc")).to_path_buf(); let mut rpc = RpcServerArgs::default().with_auth_ipc(); rpc.ws = false; @@ -356,10 +341,7 @@ pub fn default_node_config() -> NodeConfig { network.discovery.disable_discovery = true; let datadir = DatadirArgs { - datadir: data_path - .to_string_lossy() - .parse() - .expect("Failed to parse data dir path"), + datadir: data_path.to_string_lossy().parse().expect("Failed to parse data dir path"), static_files_path: None, }; @@ -392,10 +374,7 @@ fn pool_component(args: &OpRbuilderArgs) -> OpPoolBuilder { // to garbage collect transactions out of the bundle range. rollup_args.enable_tx_conditional || args.enable_revert_protection, ) - .with_supervisor( - rollup_args.supervisor_http.clone(), - rollup_args.supervisor_safety_level, - ) + .with_supervisor(rollup_args.supervisor_http.clone(), rollup_args.supervisor_safety_level) } async fn spawn_attestation_provider() -> eyre::Result { @@ -443,11 +422,7 @@ impl FlashblocksListener { } }); - Self { - flashblocks, - cancellation_token, - handle, - } + Self { flashblocks, cancellation_token, handle } } /// Get a snapshot of all received flashblocks @@ -457,11 +432,7 @@ impl FlashblocksListener { /// Find a flashblock by index pub fn find_flashblock(&self, index: u64) -> Option { - self.flashblocks - .lock() - .iter() - .find(|fb| fb.index == index) - .cloned() + self.flashblocks.lock().iter().find(|fb| fb.index == index).cloned() } /// Check if any flashblock contains the given transaction hash diff --git a/crates/builder/op-rbuilder/src/tests/framework/macros/src/lib.rs b/crates/builder/op-rbuilder/src/tests/framework/macros/src/lib.rs index daa88c7e..fef7f8df 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/macros/src/lib.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/macros/src/lib.rs @@ -207,9 +207,7 @@ pub fn rb_test(args: TokenStream, input: TokenStream) -> TokenStream { // Create the original function without test attributes (helper function) let mut helper_fn = input_fn.clone(); - helper_fn - .attrs - .retain(|attr| !attr.path().is_ident("test") && !attr.path().is_ident("tokio")); + helper_fn.attrs.retain(|attr| !attr.path().is_ident("test") && !attr.path().is_ident("tokio")); let original_name = &input_fn.sig.ident; let mut generated_functions = vec![quote! { #helper_fn }]; @@ -260,12 +258,7 @@ fn validate_signature(item_fn: &ItemFn) { panic!("Function must have exactly one parameter of type LocalInstance."); } - let output_types = item_fn - .sig - .output - .to_token_stream() - .to_string() - .replace(" ", ""); + let output_types = item_fn.sig.output.to_token_stream().to_string().replace(" ", ""); if output_types != "->eyre::Result<()>" { panic!("Function must return Result<(), eyre::Error>. Actual: {output_types}",); diff --git a/crates/builder/op-rbuilder/src/tests/framework/mod.rs b/crates/builder/op-rbuilder/src/tests/framework/mod.rs index b259215b..6c60ef3e 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/mod.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/mod.rs @@ -74,9 +74,7 @@ fn init_tests() { .with(tracing_subscriber::fmt::layer()) .with(filter_fn(move |metadata| { metadata.level() <= &level - && !prefix_blacklist - .iter() - .any(|prefix| metadata.target().starts_with(prefix)) + && !prefix_blacklist.iter().any(|prefix| metadata.target().starts_with(prefix)) })) .init(); } diff --git a/crates/builder/op-rbuilder/src/tests/framework/txs.rs b/crates/builder/op-rbuilder/src/tests/framework/txs.rs index 35872764..92041533 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/txs.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/txs.rs @@ -1,14 +1,10 @@ -use crate::{ - primitives::bundle::{Bundle, BundleResult}, - tests::funded_signer, - tx::FBPooledTransaction, - tx_signer::Signer, -}; +use core::cmp::max; +use std::{collections::VecDeque, sync::Arc}; + use alloy_consensus::TxEip1559; -use alloy_eips::{BlockNumberOrTag, eip2718::Encodable2718}; +use alloy_eips::{BlockNumberOrTag, eip1559::MIN_PROTOCOL_BASE_FEE, eip2718::Encodable2718}; use alloy_primitives::{Address, B256, Bytes, TxHash, TxKind, U256, hex}; use alloy_provider::{PendingTransactionBuilder, Provider, RootProvider}; -use core::cmp::max; use dashmap::DashMap; use futures::StreamExt; use moka::future::Cache; @@ -16,11 +12,15 @@ use op_alloy_consensus::{OpTxEnvelope, OpTypedTransaction}; use op_alloy_network::Optimism; use reth_primitives::Recovered; use reth_transaction_pool::{AllTransactionsEvents, FullTransactionEvent, TransactionEvent}; -use std::{collections::VecDeque, sync::Arc}; use tokio::sync::watch; use tracing::debug; -use alloy_eips::eip1559::MIN_PROTOCOL_BASE_FEE; +use crate::{ + primitives::bundle::{Bundle, BundleResult}, + tests::funded_signer, + tx::FBPooledTransaction, + tx_signer::Signer, +}; #[derive(Clone, Copy, Default)] pub struct BundleOpts { @@ -82,11 +82,7 @@ impl TransactionBuilder { signer: None, nonce: None, base_fee: None, - tx: TxEip1559 { - chain_id: 901, - gas_limit: 210000, - ..Default::default() - }, + tx: TxEip1559 { chain_id: 901, gas_limit: 210000, ..Default::default() }, bundle_opts: None, with_reverted_hash: false, } @@ -193,9 +189,7 @@ impl TransactionBuilder { self.tx.max_fee_per_gas = base_fee + self.tx.max_priority_fee_per_gas; } - signer - .sign_tx(OpTypedTransaction::Eip1559(self.tx)) - .expect("Failed to sign transaction") + signer.sign_tx(OpTypedTransaction::Eip1559(self.tx)).expect("Failed to sign transaction") } pub async fn send(self) -> eyre::Result> { @@ -210,11 +204,7 @@ impl TransactionBuilder { // Send the transaction as a bundle with the bundle options let bundle = Bundle { transactions: vec![transaction_encoded.into()], - reverting_hashes: if with_reverted_hash { - Some(vec![txn_hash]) - } else { - None - }, + reverting_hashes: if with_reverted_hash { Some(vec![txn_hash]) } else { None }, block_number_min: bundle_opts.block_number_min, block_number_max: bundle_opts.block_number_max, flashblock_number_min: bundle_opts.flashblock_number_min, @@ -223,20 +213,13 @@ impl TransactionBuilder { max_timestamp: bundle_opts.max_timestamp, }; - let result: BundleResult = provider - .client() - .request("eth_sendBundle", (bundle,)) - .await?; + let result: BundleResult = + provider.client().request("eth_sendBundle", (bundle,)).await?; - return Ok(PendingTransactionBuilder::new( - provider.root().clone(), - result.bundle_hash, - )); + return Ok(PendingTransactionBuilder::new(provider.root().clone(), result.bundle_hash)); } - Ok(provider - .send_raw_transaction(transaction_encoded.as_slice()) - .await?) + Ok(provider.send_raw_transaction(transaction_encoded.as_slice()).await?) } } @@ -316,16 +299,11 @@ impl TransactionPoolObserver { } }); - Self { - observations, - term: Some(term), - } + Self { observations, term: Some(term) } } pub fn tx_status(&self, txhash: TxHash) -> Option { - self.observations - .get(&txhash) - .and_then(|history| history.back().cloned()) + self.observations.get(&txhash).and_then(|history| history.back().cloned()) } pub fn is_pending(&self, txhash: TxHash) -> bool { @@ -341,10 +319,7 @@ impl TransactionPoolObserver { } pub fn count(&self, status: TransactionEvent) -> usize { - self.observations - .iter() - .filter(|tx| tx.value().back() == Some(&status)) - .count() + self.observations.iter().filter(|tx| tx.value().back() == Some(&status)).count() } pub fn pending_count(&self) -> usize { @@ -361,9 +336,7 @@ impl TransactionPoolObserver { /// Returns the history of pool events for a transaction. pub fn history(&self, txhash: TxHash) -> Option> { - self.observations - .get(&txhash) - .map(|history| history.iter().cloned().collect()) + self.observations.get(&txhash).map(|history| history.iter().cloned().collect()) } pub fn print_all(&self) { diff --git a/crates/builder/op-rbuilder/src/tests/framework/utils.rs b/crates/builder/op-rbuilder/src/tests/framework/utils.rs index 99772de1..8d7ed65a 100644 --- a/crates/builder/op-rbuilder/src/tests/framework/utils.rs +++ b/crates/builder/op-rbuilder/src/tests/framework/utils.rs @@ -1,18 +1,10 @@ -use crate::{ - tests::{ - BUILDER_PRIVATE_KEY, COMMIT_HASH, FLASHBLOCKS_DEPLOY_KEY, FLASHTESTATION_DEPLOY_KEY, - Protocol, SOURCE_LOCATORS, WORKLOAD_ID, block_builder_policy::BlockBuilderPolicy, - flashblocks_number_contract::FlashblocksNumber, - flashtestation_registry::FlashtestationRegistry, framework::driver::ChainDriver, - mock_dcap_attestation::MockAutomataDcapAttestationFee, - }, - tx_signer::Signer, -}; +use core::future::Future; +use std::{net::TcpListener, sync::Arc}; + use alloy_eips::Encodable2718; use alloy_primitives::{Address, B256, BlockHash, TxHash, TxKind, U256, hex}; use alloy_rpc_types_eth::{Block, BlockTransactionHashes}; use alloy_sol_types::SolCall; -use core::future::Future; use op_alloy_consensus::{OpTypedTransaction, TxDeposit}; use op_alloy_rpc_types::Transaction; use reth_db::{ @@ -22,9 +14,18 @@ use reth_db::{ }; use reth_node_core::{args::DatadirArgs, dirs::DataDirPath, node_config::NodeConfig}; use reth_optimism_chainspec::OpChainSpec; -use std::{net::TcpListener, sync::Arc}; use super::{FUNDED_PRIVATE_KEY, TransactionBuilder}; +use crate::{ + tests::{ + BUILDER_PRIVATE_KEY, COMMIT_HASH, FLASHBLOCKS_DEPLOY_KEY, FLASHTESTATION_DEPLOY_KEY, + Protocol, SOURCE_LOCATORS, WORKLOAD_ID, block_builder_policy::BlockBuilderPolicy, + flashblocks_number_contract::FlashblocksNumber, + flashtestation_registry::FlashtestationRegistry, framework::driver::ChainDriver, + mock_dcap_attestation::MockAutomataDcapAttestationFee, + }, + tx_signer::Signer, +}; pub trait TransactionBuilderExt { fn random_valid_transfer(self) -> Self; @@ -74,23 +75,17 @@ impl TransactionBuilderExt for TransactionBuilder { let init_data = FlashblocksNumber::initializeCall { _owner: owner.address, - _initialBuilders: if register_builder { - vec![builder_signer.address] - } else { - vec![] - }, + _initialBuilders: if register_builder { vec![builder_signer.address] } else { vec![] }, } .abi_encode(); - self.with_input(init_data.into()) - .with_signer(flashblocks_number_signer()) + self.with_input(init_data.into()).with_signer(flashblocks_number_signer()) } fn add_authorized_builder(self, builder: Address) -> Self { let calldata = FlashblocksNumber::addBuilderCall { builder }.abi_encode(); - self.with_input(calldata.into()) - .with_signer(flashblocks_number_signer()) + self.with_input(calldata.into()).with_signer(flashblocks_number_signer()) } fn deploy_flashtestation_registry_contract(self) -> Self { @@ -128,23 +123,18 @@ impl TransactionBuilderExt for TransactionBuilder { } .abi_encode(); - self.with_input(init_data.into()) - .with_signer(flashtestations_signer()) + self.with_input(init_data.into()).with_signer(flashtestations_signer()) } fn add_workload_to_policy(self) -> Self { let workload = BlockBuilderPolicy::addWorkloadToPolicyCall { workloadId: WORKLOAD_ID, commitHash: COMMIT_HASH.to_string(), - sourceLocators: SOURCE_LOCATORS - .iter() - .map(|source| source.to_string()) - .collect(), + sourceLocators: SOURCE_LOCATORS.iter().map(|source| source.to_string()).collect(), } .abi_encode(); - self.with_input(workload.into()) - .with_signer(flashtestations_signer()) + self.with_input(workload.into()).with_signer(flashtestations_signer()) } fn deploy_mock_dcap_contract(self) -> Self { @@ -164,9 +154,7 @@ impl TransactionBuilderExt for TransactionBuilder { _output: include_bytes!("./artifacts/quote-output.bin").into(), } .abi_encode(); - self.with_input(quote.into()) - .with_gas_limit(500_000) - .with_signer(flashtestations_signer()) + self.with_input(quote.into()).with_gas_limit(500_000).with_signer(flashtestations_signer()) } } @@ -186,8 +174,7 @@ pub trait ChainDriverExt { ) -> impl Future>> { async move { let accounts = (0..count).map(|_| Signer::random()).collect::>(); - self.fund_many(accounts.iter().map(|a| a.address).collect(), amount) - .await?; + self.fund_many(accounts.iter().map(|a| a.address).collect(), amount).await?; Ok(accounts) } } @@ -241,32 +228,20 @@ impl ChainDriverExt for ChainDriver

{ let signer = Signer::random(); let signed_tx = signer.sign_tx(OpTypedTransaction::Deposit(deposit))?; let signed_tx_rlp = signed_tx.encoded_2718(); - Ok(self - .build_new_block_with_txs(vec![signed_tx_rlp.into()]) - .await? - .header - .hash) + Ok(self.build_new_block_with_txs(vec![signed_tx_rlp.into()]).await?.header.hash) } async fn build_new_block_with_valid_transaction( &self, ) -> eyre::Result<(TxHash, Block)> { - let tx = self - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let tx = self.create_transaction().random_valid_transfer().send().await?; Ok((*tx.tx_hash(), self.build_new_block().await?)) } async fn build_new_block_with_reverting_transaction( &self, ) -> eyre::Result<(TxHash, Block)> { - let tx = self - .create_transaction() - .random_reverting_transaction() - .send() - .await?; + let tx = self.create_transaction().random_reverting_transaction().send().await?; Ok((*tx.tx_hash(), self.build_new_block().await?)) } @@ -278,18 +253,14 @@ pub trait BlockTransactionsExt { impl BlockTransactionsExt for Block { fn includes(&self, txs: &impl AsTxs) -> bool { - txs.as_txs() - .into_iter() - .all(|tx| self.transactions.hashes().any(|included| included == tx)) + txs.as_txs().into_iter().all(|tx| self.transactions.hashes().any(|included| included == tx)) } } impl BlockTransactionsExt for BlockTransactionHashes<'_, Transaction> { fn includes(&self, txs: &impl AsTxs) -> bool { let mut included_tx_iter = self.clone(); - txs.as_txs() - .iter() - .all(|tx| included_tx_iter.any(|included| included == *tx)) + txs.as_txs().iter().all(|tx| included_tx_iter.any(|included| included == *tx)) } } @@ -325,10 +296,8 @@ pub fn create_test_db(config: NodeConfig) -> Arc::from( reth_db::test_utils::tempdir_path(), ); - let db_config = config.with_datadir_args(DatadirArgs { - datadir: path.clone(), - ..Default::default() - }); + let db_config = + config.with_datadir_args(DatadirArgs { datadir: path.clone(), ..Default::default() }); let data_dir = path.unwrap_or_chain_default(db_config.chain.chain(), db_config.datadir.clone()); let path = data_dir.db(); let db = init_db( @@ -355,18 +324,14 @@ pub fn get_available_port() -> u16 { pub fn builder_signer() -> Signer { Signer::try_from_secret( - BUILDER_PRIVATE_KEY - .parse() - .expect("invalid hardcoded builder private key"), + BUILDER_PRIVATE_KEY.parse().expect("invalid hardcoded builder private key"), ) .expect("Failed to create signer from hardcoded builder private key") } pub fn funded_signer() -> Signer { Signer::try_from_secret( - FUNDED_PRIVATE_KEY - .parse() - .expect("invalid hardcoded funded private key"), + FUNDED_PRIVATE_KEY.parse().expect("invalid hardcoded funded private key"), ) .expect("Failed to create signer from hardcoded funded private key") } diff --git a/crates/builder/op-rbuilder/src/tests/gas_limiter.rs b/crates/builder/op-rbuilder/src/tests/gas_limiter.rs index 00dfb035..877d97a1 100644 --- a/crates/builder/op-rbuilder/src/tests/gas_limiter.rs +++ b/crates/builder/op-rbuilder/src/tests/gas_limiter.rs @@ -1,11 +1,13 @@ +use std::collections::HashSet; + +use macros::rb_test; +use tracing::info; + use crate::{ args::OpRbuilderArgs, gas_limiter::args::GasLimiterArgs, tests::{ChainDriverExt, LocalInstance, TransactionBuilderExt}, }; -use macros::rb_test; -use std::collections::HashSet; -use tracing::info; /// Integration test for the gas limiter functionality. /// Tests that gas limits are properly enforced during actual block building @@ -23,9 +25,7 @@ async fn gas_limiter_blocks_excessive_usage(rbuilder: LocalInstance) -> eyre::Re let driver = rbuilder.driver().await?; // Fund some accounts for testing - let funded_accounts = driver - .fund_accounts(2, 10_000_000_000_000_000_000u128) - .await?; // 10 ETH each + let funded_accounts = driver.fund_accounts(2, 10_000_000_000_000_000_000u128).await?; // 10 ETH each // These transactions should not be throttled let tx1 = driver @@ -59,11 +59,7 @@ async fn gas_limiter_blocks_excessive_usage(rbuilder: LocalInstance) -> eyre::Re .send() .await?; sent_txs.push(*big_tx.tx_hash()); - info!( - "Sent big transaction {} from address {}", - i + 1, - funded_accounts[0].address - ); + info!("Sent big transaction {} from address {}", i + 1, funded_accounts[0].address); } // Meanwhile, the other address should not be throttled @@ -87,10 +83,7 @@ async fn gas_limiter_blocks_excessive_usage(rbuilder: LocalInstance) -> eyre::Re "Gas limiter should have rejected some transactions, included: {}/5", included_count ); - assert!( - included_count > 0, - "Gas limiter should have allowed at least one transaction" - ); + assert!(included_count > 0, "Gas limiter should have allowed at least one transaction"); assert!( tx_hashes.contains(legit_tx.tx_hash()), diff --git a/crates/builder/op-rbuilder/src/tests/miner_gas_limit.rs b/crates/builder/op-rbuilder/src/tests/miner_gas_limit.rs index 619509db..5f401c72 100644 --- a/crates/builder/op-rbuilder/src/tests/miner_gas_limit.rs +++ b/crates/builder/op-rbuilder/src/tests/miner_gas_limit.rs @@ -1,27 +1,23 @@ -use crate::tests::{BlockTransactionsExt, LocalInstance}; use alloy_provider::Provider; use macros::{if_flashblocks, if_standard, rb_test}; +use crate::tests::{BlockTransactionsExt, LocalInstance}; + /// This test ensures that the miner gas limit is respected /// We will set the limit to 60,000 and see that the builder will not include any transactions #[rb_test] async fn miner_gas_limit(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let call = driver - .provider() - .raw_request::<(u64,), bool>("miner_setGasLimit".into(), (60000,)) - .await?; + let call = + driver.provider().raw_request::<(u64,), bool>("miner_setGasLimit".into(), (60000,)).await?; assert!(call, "miner_setGasLimit should be executed successfully"); let unfit_tx = driver.create_transaction().send().await?; let block = driver.build_new_block().await?; // tx should not be included because the gas limit is less than the transaction gas - assert!( - !block.includes(unfit_tx.tx_hash()), - "transaction should not be included in the block" - ); + assert!(!block.includes(unfit_tx.tx_hash()), "transaction should not be included in the block"); Ok(()) } @@ -62,17 +58,9 @@ async fn block_fill(rbuilder: LocalInstance) -> eyre::Result<()> { let block = driver.build_new_block().await?; for (i, tx_hash) in tx_hashes.iter().enumerate() { - assert!( - block.includes(tx_hash), - "tx i={} hash={} should be in block", - i, - tx_hash - ); + assert!(block.includes(tx_hash), "tx i={} hash={} should be in block", i, tx_hash); } - assert!( - !block.includes(unfit_tx.tx_hash()), - "unfit tx should not be in block" - ); + assert!(!block.includes(unfit_tx.tx_hash()), "unfit tx should not be in block"); if_standard! { assert_eq!( @@ -99,29 +87,19 @@ async fn block_fill(rbuilder: LocalInstance) -> eyre::Result<()> { async fn reset_gas_limit(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let call = driver - .provider() - .raw_request::<(u64,), bool>("miner_setGasLimit".into(), (60000,)) - .await?; + let call = + driver.provider().raw_request::<(u64,), bool>("miner_setGasLimit".into(), (60000,)).await?; assert!(call, "miner_setGasLimit should be executed successfully"); let unfit_tx = driver.create_transaction().send().await?; let block = driver.build_new_block().await?; // tx should not be included because the gas limit is less than the transaction gas - assert!( - !block.includes(unfit_tx.tx_hash()), - "transaction should not be included in the block" - ); + assert!(!block.includes(unfit_tx.tx_hash()), "transaction should not be included in the block"); - let reset_call = driver - .provider() - .raw_request::<(u64,), bool>("miner_setGasLimit".into(), (0,)) - .await?; - assert!( - reset_call, - "miner_setGasLimit should be executed successfully" - ); + let reset_call = + driver.provider().raw_request::<(u64,), bool>("miner_setGasLimit".into(), (0,)).await?; + assert!(reset_call, "miner_setGasLimit should be executed successfully"); let _ = driver.build_new_block().await?; @@ -129,10 +107,7 @@ async fn reset_gas_limit(rbuilder: LocalInstance) -> eyre::Result<()> { let block = driver.build_new_block().await?; // tx should be included because the gas limit is reset to the default value - assert!( - block.includes(fit_tx.tx_hash()), - "transaction should be in block" - ); + assert!(block.includes(fit_tx.tx_hash()), "transaction should be in block"); Ok(()) } diff --git a/crates/builder/op-rbuilder/src/tests/ordering.rs b/crates/builder/op-rbuilder/src/tests/ordering.rs index bba31b0e..15e86c70 100644 --- a/crates/builder/op-rbuilder/src/tests/ordering.rs +++ b/crates/builder/op-rbuilder/src/tests/ordering.rs @@ -1,8 +1,9 @@ -use crate::tests::{ChainDriverExt, LocalInstance, framework::ONE_ETH}; use alloy_consensus::Transaction; use futures::{StreamExt, future::join_all, stream}; use macros::rb_test; +use crate::tests::{ChainDriverExt, LocalInstance, framework::ONE_ETH}; + /// This test ensures that the transactions are ordered by fee priority in the block. /// This version of the test is only applicable to the standard builder because in flashblocks /// the transaction order is commited by the block after each flashblock is produced, @@ -63,10 +64,7 @@ async fn fee_priority_ordering(rbuilder: LocalInstance) -> eyre::Result<()> { .rev() // we want to check descending order .collect::>(); - assert!( - txs_tips.is_sorted(), - "Transactions not ordered by fee priority" - ); + assert!(txs_tips.is_sorted(), "Transactions not ordered by fee priority"); Ok(()) } diff --git a/crates/builder/op-rbuilder/src/tests/revert.rs b/crates/builder/op-rbuilder/src/tests/revert.rs index 76e1c5b9..26dda657 100644 --- a/crates/builder/op-rbuilder/src/tests/revert.rs +++ b/crates/builder/op-rbuilder/src/tests/revert.rs @@ -73,17 +73,10 @@ async fn disabled(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; for _ in 0..10 { - let valid_tx = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; + let valid_tx = driver.create_transaction().random_valid_transfer().send().await?; - let reverting_tx = driver - .create_transaction() - .random_reverting_transaction() - .send() - .await?; + let reverting_tx = + driver.create_transaction().random_reverting_transaction().send().await?; let block = driver.build_new_block().await?; assert!(block.includes(valid_tx.tx_hash())); @@ -99,16 +92,9 @@ async fn disabled(rbuilder: LocalInstance) -> eyre::Result<()> { async fn disabled_bundle_endpoint_error(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; - let res = driver - .create_transaction() - .with_bundle(BundleOpts::default()) - .send() - .await; + let res = driver.create_transaction().with_bundle(BundleOpts::default()).send().await; - assert!( - res.is_err(), - "Expected error because method is not available" - ); + assert!(res.is_err(), "Expected error because method is not available"); Ok(()) } @@ -133,12 +119,7 @@ async fn bundle(rbuilder: LocalInstance) -> eyre::Result<()> { .await?; let block2 = driver.build_new_block().await?; // Block 2 - assert!( - block2 - .transactions - .hashes() - .includes(valid_bundle.tx_hash()) - ); + assert!(block2.transactions.hashes().includes(valid_bundle.tx_hash())); let bundle_opts = BundleOpts::default().with_block_number_max(4); @@ -194,11 +175,7 @@ async fn bundle_min_block_number(rbuilder: LocalInstance) -> eyre::Result<()> { .create_transaction() .with_revert() .with_reverted_hash() - .with_bundle( - BundleOpts::default() - .with_block_number_max(4) - .with_block_number_min(4), - ) + .with_bundle(BundleOpts::default().with_block_number_max(4).with_block_number_min(4)) .send() .await?; @@ -257,22 +234,14 @@ async fn bundle_range_limits(rbuilder: LocalInstance) -> eyre::Result<()> { } // Max block cannot be a past block - assert!( - send_bundle(&driver, BundleOpts::default().with_block_number_max(1)) - .await - .is_err() - ); + assert!(send_bundle(&driver, BundleOpts::default().with_block_number_max(1)).await.is_err()); // Bundles are valid if their max block in in between the current block and the max block range let current_block = 2; let next_valid_block = current_block + 1; for i in next_valid_block..next_valid_block + MAX_BLOCK_RANGE_BLOCKS { - assert!( - send_bundle(&driver, BundleOpts::default().with_block_number_max(i)) - .await - .is_ok() - ); + assert!(send_bundle(&driver, BundleOpts::default().with_block_number_max(i)).await.is_ok()); } // A bundle with a block out of range is invalid @@ -290,9 +259,7 @@ async fn bundle_range_limits(rbuilder: LocalInstance) -> eyre::Result<()> { assert!( send_bundle( &driver, - BundleOpts::default() - .with_block_number_max(1) - .with_block_number_min(2) + BundleOpts::default().with_block_number_max(1).with_block_number_min(2) ) .await .is_err() @@ -310,12 +277,9 @@ async fn bundle_range_limits(rbuilder: LocalInstance) -> eyre::Result<()> { .is_ok() ); assert!( - send_bundle( - &driver, - BundleOpts::default().with_block_number_max(next_valid_block) - ) - .await - .is_ok() + send_bundle(&driver, BundleOpts::default().with_block_number_max(next_valid_block)) + .await + .is_ok() ); // A bundle with a min block equal to max block is valid @@ -334,38 +298,26 @@ async fn bundle_range_limits(rbuilder: LocalInstance) -> eyre::Result<()> { // A bundle with only min block that's within the default range is valid let default_max = current_block + MAX_BLOCK_RANGE_BLOCKS; assert!( - send_bundle( - &driver, - BundleOpts::default().with_block_number_min(current_block) - ) - .await - .is_ok() + send_bundle(&driver, BundleOpts::default().with_block_number_min(current_block)) + .await + .is_ok() ); assert!( - send_bundle( - &driver, - BundleOpts::default().with_block_number_min(default_max - 1) - ) - .await - .is_ok() + send_bundle(&driver, BundleOpts::default().with_block_number_min(default_max - 1)) + .await + .is_ok() ); assert!( - send_bundle( - &driver, - BundleOpts::default().with_block_number_min(default_max) - ) - .await - .is_ok() + send_bundle(&driver, BundleOpts::default().with_block_number_min(default_max)) + .await + .is_ok() ); // A bundle with only min block that exceeds the default max range is invalid assert!( - send_bundle( - &driver, - BundleOpts::default().with_block_number_min(default_max + 1) - ) - .await - .is_err() + send_bundle(&driver, BundleOpts::default().with_block_number_min(default_max + 1)) + .await + .is_err() ); Ok(()) @@ -382,16 +334,9 @@ async fn allow_reverted_transactions_without_bundle(rbuilder: LocalInstance) -> let driver = rbuilder.driver().await?; for _ in 0..10 { - let valid_tx = driver - .create_transaction() - .random_valid_transfer() - .send() - .await?; - let reverting_tx = driver - .create_transaction() - .random_reverting_transaction() - .send() - .await?; + let valid_tx = driver.create_transaction().random_valid_transfer().send().await?; + let reverting_tx = + driver.create_transaction().random_reverting_transaction().send().await?; let block = driver.build_new_block().await?; assert!(block.includes(valid_tx.tx_hash())); diff --git a/crates/builder/op-rbuilder/src/tests/smoke.rs b/crates/builder/op-rbuilder/src/tests/smoke.rs index 63cfa77b..04aa8680 100644 --- a/crates/builder/op-rbuilder/src/tests/smoke.rs +++ b/crates/builder/op-rbuilder/src/tests/smoke.rs @@ -1,18 +1,19 @@ -use crate::{ - args::OpRbuilderArgs, - tests::{LocalInstance, TransactionBuilderExt}, -}; -use alloy_primitives::TxHash; - use core::{ sync::atomic::{AtomicBool, Ordering}, time::Duration, }; -use macros::{if_flashblocks, if_standard, rb_test}; use std::collections::HashSet; + +use alloy_primitives::TxHash; +use macros::{if_flashblocks, if_standard, rb_test}; use tokio::{join, task::yield_now}; use tracing::info; +use crate::{ + args::OpRbuilderArgs, + tests::{LocalInstance, TransactionBuilderExt}, +}; + /// This is a smoke test that ensures that transactions are included in blocks /// and that the block generator is functioning correctly. /// @@ -23,9 +24,7 @@ async fn chain_produces_blocks(rbuilder: LocalInstance) -> eyre::Result<()> { let driver = rbuilder.driver().await?; #[cfg(target_os = "linux")] - let driver = driver - .with_validation_node(crate::tests::ExternalNode::reth().await?) - .await?; + let driver = driver.with_validation_node(crate::tests::ExternalNode::reth().await?).await?; const SAMPLE_SIZE: usize = 10; @@ -119,12 +118,7 @@ async fn produces_blocks_under_load_within_deadline(rbuilder: LocalInstance) -> async { // Keep the builder busy with new transactions. loop { - match driver - .create_transaction() - .random_valid_transfer() - .send() - .await - { + match driver.create_transaction().random_valid_transfer().send().await { Ok(_) => {} Err(e) if e.to_string().contains("txpool is full") => { // If the txpool is full, give it a short break @@ -202,9 +196,7 @@ async fn chain_produces_big_tx_with_gas_limit(rbuilder: LocalInstance) -> eyre:: let driver = rbuilder.driver().await?; #[cfg(target_os = "linux")] - let driver = driver - .with_validation_node(crate::tests::ExternalNode::reth().await?) - .await?; + let driver = driver.with_validation_node(crate::tests::ExternalNode::reth().await?).await?; // insert valid txn under limit let tx = driver @@ -259,9 +251,7 @@ async fn chain_produces_big_tx_without_gas_limit(rbuilder: LocalInstance) -> eyr let driver = rbuilder.driver().await?; #[cfg(target_os = "linux")] - let driver = driver - .with_validation_node(crate::tests::ExternalNode::reth().await?) - .await?; + let driver = driver.with_validation_node(crate::tests::ExternalNode::reth().await?).await?; // insert txn with gas usage but there is no limit let tx = driver diff --git a/crates/builder/op-rbuilder/src/tests/txpool.rs b/crates/builder/op-rbuilder/src/tests/txpool.rs index dbb369d2..fed14211 100644 --- a/crates/builder/op-rbuilder/src/tests/txpool.rs +++ b/crates/builder/op-rbuilder/src/tests/txpool.rs @@ -1,11 +1,12 @@ -use crate::tests::{ - BlockTransactionsExt, ChainDriverExt, LocalInstance, ONE_ETH, default_node_config, -}; use macros::rb_test; use reth_node_builder::NodeConfig; use reth_node_core::args::TxPoolArgs; use reth_optimism_chainspec::OpChainSpec; +use crate::tests::{ + BlockTransactionsExt, ChainDriverExt, LocalInstance, ONE_ETH, default_node_config, +}; + /// This test ensures that pending pool custom limit is respected and priority tx would be included even when pool if full. #[rb_test( config = NodeConfig:: { @@ -26,11 +27,7 @@ async fn pending_pool_limit(rbuilder: LocalInstance) -> eyre::Result<()> { let acc_with_priority = accounts.last().unwrap(); for _ in 0..50 { - let _ = driver - .create_transaction() - .with_signer(*acc_no_priority) - .send() - .await?; + let _ = driver.create_transaction().with_signer(*acc_no_priority).send().await?; } assert_eq!( diff --git a/crates/builder/op-rbuilder/src/tx.rs b/crates/builder/op-rbuilder/src/tx.rs index 64f7e43f..2848b642 100644 --- a/crates/builder/op-rbuilder/src/tx.rs +++ b/crates/builder/op-rbuilder/src/tx.rs @@ -233,9 +233,7 @@ impl EthPoolTransaction for FBPooledTransaction { _sidecar: &BlobTransactionSidecarVariant, _settings: &KzgSettings, ) -> Result<(), BlobTransactionValidationError> { - Err(BlobTransactionValidationError::NotBlobTransaction( - self.ty(), - )) + Err(BlobTransactionValidationError::NotBlobTransaction(self.ty())) } } diff --git a/crates/builder/op-rbuilder/src/tx_data_store.rs b/crates/builder/op-rbuilder/src/tx_data_store.rs index 05dd1d10..fd837dcd 100644 --- a/crates/builder/op-rbuilder/src/tx_data_store.rs +++ b/crates/builder/op-rbuilder/src/tx_data_store.rs @@ -1,13 +1,3 @@ -use crate::{metrics::OpRBuilderMetrics, tx::FBPooledTransaction}; -use alloy_consensus::Transaction; -use alloy_primitives::{Address, TxHash}; -use concurrent_queue::ConcurrentQueue; -use jsonrpsee::{ - core::{RpcResult, async_trait}, - proc_macros::rpc, -}; -use reth_optimism_txpool::OpPooledTransaction; -use reth_transaction_pool::PoolTransaction; use std::{ fmt::Debug, sync::{ @@ -16,10 +6,22 @@ use std::{ }, time::Instant, }; + +use alloy_consensus::Transaction; +use alloy_primitives::{Address, TxHash}; use base_bundles::{AcceptedBundle, MeterBundleResponse}; +use concurrent_queue::ConcurrentQueue; +use jsonrpsee::{ + core::{RpcResult, async_trait}, + proc_macros::rpc, +}; +use reth_optimism_txpool::OpPooledTransaction; +use reth_transaction_pool::PoolTransaction; use tracing::{debug, info, warn}; use uuid::Uuid; +use crate::{metrics::OpRBuilderMetrics, tx::FBPooledTransaction}; + #[derive(Clone)] pub struct StoredBackrunBundle { pub bundle_id: Uuid, @@ -50,10 +52,7 @@ impl Debug for TxDataStore { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("TxDataStore") .field("entries", &self.data.by_tx_hash.len()) - .field( - "metering_enabled", - &self.data.metering_enabled.load(Ordering::Relaxed), - ) + .field("metering_enabled", &self.data.metering_enabled.load(Ordering::Relaxed)) .finish() } } @@ -90,10 +89,7 @@ impl TxDataStore { if metering_enabled { self.metrics.metering_unknown_transaction.increment(1); } - return TxData { - metering: None, - backrun_bundles: vec![], - }; + return TxData { metering: None, backrun_bundles: vec![] }; }; let data = entry.clone(); @@ -139,10 +135,8 @@ impl TxDataStore { self.evict_if_needed(); let _ = self.data.lru.push(target_tx_hash); - let total_priority_fee: u128 = backrun_txs - .iter() - .map(|tx| tx.max_priority_fee_per_gas().unwrap_or(0)) - .sum(); + let total_priority_fee: u128 = + backrun_txs.iter().map(|tx| tx.max_priority_fee_per_gas().unwrap_or(0)).sum(); let stored_bundle = StoredBackrunBundle { bundle_id: *bundle.uuid(), @@ -153,10 +147,8 @@ impl TxDataStore { let replaced = { let mut entry = self.data.by_tx_hash.entry(target_tx_hash).or_default(); - let replaced = if let Some(pos) = entry - .backrun_bundles - .iter() - .position(|b| b.sender == backrun_sender) + let replaced = if let Some(pos) = + entry.backrun_bundles.iter().position(|b| b.sender == backrun_sender) { entry.backrun_bundles[pos] = stored_bundle; true @@ -164,9 +156,7 @@ impl TxDataStore { entry.backrun_bundles.push(stored_bundle); false }; - entry - .backrun_bundles - .sort_by(|a, b| b.total_priority_fee.cmp(&a.total_priority_fee)); + entry.backrun_bundles.sort_by(|a, b| b.total_priority_fee.cmp(&a.total_priority_fee)); replaced }; @@ -188,9 +178,7 @@ impl TxDataStore { "Stored backrun bundle" ); - self.metrics - .backrun_bundles_in_store - .set(self.data.by_tx_hash.len() as f64); + self.metrics.backrun_bundles_in_store.set(self.data.by_tx_hash.len() as f64); Ok(()) } @@ -215,9 +203,7 @@ impl TxDataStore { } } - self.metrics - .backrun_bundles_in_store - .set(self.data.by_tx_hash.len() as f64); + self.metrics.backrun_bundles_in_store.set(self.data.by_tx_hash.len() as f64); } pub fn insert_metering(&self, tx_hash: TxHash, metering_info: MeterBundleResponse) { @@ -232,9 +218,7 @@ impl TxDataStore { for mut entry in self.data.by_tx_hash.iter_mut() { entry.metering = None; } - self.data - .by_tx_hash - .retain(|_, v| v.metering.is_some() || !v.backrun_bundles.is_empty()); + self.data.by_tx_hash.retain(|_, v| v.metering.is_some() || !v.backrun_bundles.is_empty()); } pub fn set_metering_enabled(&self, enabled: bool) { @@ -283,10 +267,7 @@ pub struct TxDataStoreExt { impl TxDataStoreExt { pub fn new(store: TxDataStore) -> Self { - Self { - store, - metrics: OpRBuilderMetrics::default(), - } + Self { store, metrics: OpRBuilderMetrics::default() } } } @@ -304,9 +285,7 @@ impl BaseApiExtServer for TxDataStoreExt { None::<()>, ) })?; - self.metrics - .backrun_bundle_insert_duration - .record(start.elapsed().as_secs_f64()); + self.metrics.backrun_bundle_insert_duration.record(start.elapsed().as_secs_f64()); Ok(()) } @@ -333,7 +312,6 @@ impl BaseApiExtServer for TxDataStoreExt { #[cfg(test)] mod tests { - use super::*; use alloy_consensus::{SignableTransaction, transaction::Recovered}; use alloy_primitives::{Address, B256, TxHash, U256}; use alloy_provider::network::TxSignerSync; @@ -341,6 +319,8 @@ mod tests { use op_alloy_consensus::OpTxEnvelope; use op_alloy_rpc_types::OpTransactionRequest; + use super::*; + fn create_recovered_tx( from: &PrivateKeySigner, nonce: u64, @@ -453,10 +433,7 @@ mod tests { let data = store.get(&target_tx_hash); assert_eq!(data.backrun_bundles.len(), 1); assert_eq!(data.backrun_bundles[0].backrun_txs.len(), 1); - assert_eq!( - *data.backrun_bundles[0].backrun_txs[0].hash(), - backrun_tx1.tx_hash() - ); + assert_eq!(*data.backrun_bundles[0].backrun_txs[0].hash(), backrun_tx1.tx_hash()); let replacement_bundle = create_test_accepted_bundle(vec![target_tx.clone(), backrun_tx2.clone()]); @@ -465,10 +442,7 @@ mod tests { let data = store.get(&target_tx_hash); assert_eq!(data.backrun_bundles.len(), 1); - assert_eq!( - *data.backrun_bundles[0].backrun_txs[0].hash(), - backrun_tx2.tx_hash() - ); + assert_eq!(*data.backrun_bundles[0].backrun_txs[0].hash(), backrun_tx2.tx_hash()); store.remove_backrun_bundles(&target_tx_hash); assert!(store.get(&target_tx_hash).backrun_bundles.is_empty()); diff --git a/crates/builder/op-rbuilder/src/tx_signer.rs b/crates/builder/op-rbuilder/src/tx_signer.rs index 6b8c86d9..eee5ff66 100644 --- a/crates/builder/op-rbuilder/src/tx_signer.rs +++ b/crates/builder/op-rbuilder/src/tx_signer.rs @@ -24,11 +24,7 @@ impl Signer { let pubkey = secret.public_key(SECP256K1); let address = public_key_to_address(&pubkey); - Ok(Self { - address, - pubkey, - secret, - }) + Ok(Self { address, pubkey, secret }) } pub fn sign_message(&self, message: B256) -> Result { @@ -86,11 +82,7 @@ pub fn generate_signer() -> Signer { // Derive Ethereum address let address = public_key_to_address(&public_key); - Signer { - address, - pubkey: public_key, - secret: private_key, - } + Signer { address, pubkey: public_key, secret: private_key } } /// Converts a public key to an Ethereum address @@ -119,18 +111,15 @@ pub fn generate_key_from_seed(seed: &str) -> Signer { let public_key = PublicKey::from_secret_key(&secp, &private_key); let address = public_key_to_address(&public_key); - Signer { - address, - pubkey: public_key, - secret: private_key, - } + Signer { address, pubkey: public_key, secret: private_key } } #[cfg(test)] mod test { - use super::*; use alloy_consensus::{TxEip1559, transaction::SignerRecoverable}; use alloy_primitives::{TxKind as TransactionKind, address, fixed_bytes}; + + use super::*; #[test] fn test_sign_transaction() { let secret = @@ -166,23 +155,12 @@ mod test { let pubkey_bytes = public_key.serialize_uncompressed(); // Verify the public key format - assert_eq!( - pubkey_bytes.len(), - 65, - "Uncompressed public key should be 65 bytes" - ); - assert_eq!( - pubkey_bytes[0], 0x04, - "Uncompressed public key should start with 0x04" - ); + assert_eq!(pubkey_bytes.len(), 65, "Uncompressed public key should be 65 bytes"); + assert_eq!(pubkey_bytes[0], 0x04, "Uncompressed public key should start with 0x04"); // Verify report data would be 64 bytes let report_data = &pubkey_bytes[1..65]; - assert_eq!( - report_data.len(), - 64, - "Report data should be exactly 64 bytes" - ); + assert_eq!(report_data.len(), 64, "Report data should be exactly 64 bytes"); } #[test] @@ -195,9 +173,6 @@ mod test { let address1 = public_key_to_address(&public_key); let address2 = public_key_to_address(&public_key); - assert_eq!( - address1, address2, - "Address derivation should be deterministic" - ); + assert_eq!(address1, address2, "Address derivation should be deterministic"); } } diff --git a/crates/builder/p2p/src/behaviour.rs b/crates/builder/p2p/src/behaviour.rs index bedfb78e..3bd55b24 100644 --- a/crates/builder/p2p/src/behaviour.rs +++ b/crates/builder/p2p/src/behaviour.rs @@ -1,3 +1,5 @@ +use std::{convert::Infallible, time::Duration}; + use eyre::WrapErr as _; use libp2p::{ Swarm, autonat, @@ -5,7 +7,6 @@ use libp2p::{ identify, identity, mdns, ping, swarm::NetworkBehaviour, }; -use std::{convert::Infallible, time::Duration}; const PROTOCOL_VERSION: &str = "1.0.0"; @@ -70,14 +71,7 @@ impl Behaviour { let ping = ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(10))); let stream = libp2p_stream::Behaviour::new(); - Ok(Self { - autonat, - connection_limits, - identify, - ping, - mdns, - stream, - }) + Ok(Self { autonat, connection_limits, identify, ping, mdns, stream }) } pub(crate) fn new_control(&mut self) -> libp2p_stream::Control { diff --git a/crates/builder/p2p/src/lib.rs b/crates/builder/p2p/src/lib.rs index 757be3b2..9aa8e1cd 100644 --- a/crates/builder/p2p/src/lib.rs +++ b/crates/builder/p2p/src/lib.rs @@ -1,10 +1,11 @@ mod behaviour; mod outgoing; -use behaviour::Behaviour; -use libp2p_stream::IncomingStreams; +use std::{collections::HashMap, time::Duration}; +use behaviour::Behaviour; use eyre::Context; +pub use libp2p::{Multiaddr, StreamProtocol}; use libp2p::{ PeerId, Swarm, Transport as _, identity::{self, ed25519}, @@ -12,14 +13,12 @@ use libp2p::{ swarm::SwarmEvent, tcp, yamux, }; +use libp2p_stream::IncomingStreams; use multiaddr::Protocol; -use std::{collections::HashMap, time::Duration}; use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::{debug, warn}; -pub use libp2p::{Multiaddr, StreamProtocol}; - const DEFAULT_MAX_PEER_COUNT: u32 = 50; /// A message that can be sent between peers. @@ -86,11 +85,7 @@ impl Node { pub fn multiaddrs(&self) -> Vec { self.listen_addrs .iter() - .map(|addr| { - addr.clone() - .with_p2p(self.peer_id) - .expect("can add peer ID to multiaddr") - }) + .map(|addr| addr.clone().with_p2p(self.peer_id).expect("can add peer ID to multiaddr")) .collect() } @@ -114,9 +109,7 @@ impl Node { } = self; for addr in listen_addrs { - swarm - .listen_on(addr) - .wrap_err("swarm failed to listen on multiaddr")?; + swarm.listen_on(addr).wrap_err("swarm failed to listen on multiaddr")?; } for mut address in known_peers { @@ -127,9 +120,7 @@ impl Node { } }; swarm.add_peer_address(peer_id, address.clone()); - swarm - .dial(address) - .wrap_err("swarm failed to dial known peer")?; + swarm.dial(address).wrap_err("swarm failed to dial known peer")?; } let handles = incoming_streams_handlers @@ -368,9 +359,8 @@ impl NodeBuilder { .collect(); if listen_addrs.is_empty() { let port = port.unwrap_or(0); - let listen_addr = format!("/ip4/0.0.0.0/tcp/{port}") - .parse() - .expect("can parse valid multiaddr"); + let listen_addr = + format!("/ip4/0.0.0.0/tcp/{port}").parse().expect("can parse valid multiaddr"); listen_addrs.push(listen_addr); } @@ -409,26 +399,13 @@ impl IncomingStreamsHandler { ) -> (Self, mpsc::Receiver) { const CHANNEL_SIZE: usize = 100; let (tx, rx) = mpsc::channel(CHANNEL_SIZE); - ( - Self { - protocol, - incoming, - tx, - cancellation_token, - }, - rx, - ) + (Self { protocol, incoming, tx, cancellation_token }, rx) } async fn run(self) { use futures::StreamExt as _; - let Self { - protocol, - mut incoming, - tx, - cancellation_token, - } = self; + let Self { protocol, mut incoming, tx, cancellation_token } = self; let mut handle_stream_futures = futures::stream::FuturesUnordered::new(); loop { @@ -539,36 +516,28 @@ mod test { #[tokio::test] async fn two_nodes_can_connect_and_message() { - let NodeBuildResult { - node: node1, - outgoing_message_tx: _, - incoming_message_rxs: mut rx1, - } = NodeBuilder::new() - .with_listen_addr("/ip4/127.0.0.1/tcp/9000".parse().unwrap()) - .with_agent_version(TEST_AGENT_VERSION.to_string()) - .with_protocol(TEST_PROTOCOL) - .try_build::() - .unwrap(); - let NodeBuildResult { - node: node2, - outgoing_message_tx: tx2, - incoming_message_rxs: _, - } = NodeBuilder::new() - .with_known_peers(node1.multiaddrs()) - .with_protocol(TEST_PROTOCOL) - .with_listen_addr("/ip4/127.0.0.1/tcp/9001".parse().unwrap()) - .with_agent_version(TEST_AGENT_VERSION.to_string()) - .try_build::() - .unwrap(); + let NodeBuildResult { node: node1, outgoing_message_tx: _, incoming_message_rxs: mut rx1 } = + NodeBuilder::new() + .with_listen_addr("/ip4/127.0.0.1/tcp/9000".parse().unwrap()) + .with_agent_version(TEST_AGENT_VERSION.to_string()) + .with_protocol(TEST_PROTOCOL) + .try_build::() + .unwrap(); + let NodeBuildResult { node: node2, outgoing_message_tx: tx2, incoming_message_rxs: _ } = + NodeBuilder::new() + .with_known_peers(node1.multiaddrs()) + .with_protocol(TEST_PROTOCOL) + .with_listen_addr("/ip4/127.0.0.1/tcp/9001".parse().unwrap()) + .with_agent_version(TEST_AGENT_VERSION.to_string()) + .try_build::() + .unwrap(); tokio::spawn(async move { node1.run().await }); tokio::spawn(async move { node2.run().await }); // sleep to allow nodes to connect tokio::time::sleep(Duration::from_secs(2)).await; - let message = TestMessage { - content: "message".to_string(), - }; + let message = TestMessage { content: "message".to_string() }; tx2.send(message.clone()).await.unwrap(); let recv_message: TestMessage = rx1.remove(&TEST_PROTOCOL).unwrap().recv().await.unwrap(); diff --git a/crates/builder/p2p/src/outgoing.rs b/crates/builder/p2p/src/outgoing.rs index 2440e0f7..06fd1382 100644 --- a/crates/builder/p2p/src/outgoing.rs +++ b/crates/builder/p2p/src/outgoing.rs @@ -1,19 +1,19 @@ -use crate::Message; +use std::collections::HashMap; + use eyre::Context; use futures::stream::FuturesUnordered; use libp2p::{PeerId, StreamProtocol, swarm::Stream}; -use std::collections::HashMap; use tracing::{debug, warn}; +use crate::Message; + pub(crate) struct StreamsHandler { peers_to_stream: HashMap>, } impl StreamsHandler { pub(crate) fn new() -> Self { - Self { - peers_to_stream: HashMap::new(), - } + Self { peers_to_stream: HashMap::new() } } pub(crate) fn has_peer(&self, peer: &PeerId) -> bool { @@ -26,10 +26,7 @@ impl StreamsHandler { protocol: StreamProtocol, stream: Stream, ) { - self.peers_to_stream - .entry(peer) - .or_default() - .insert(protocol, stream); + self.peers_to_stream.entry(peer).or_default().insert(protocol, stream); } pub(crate) fn remove_peer(&mut self, peer: &PeerId) { @@ -44,17 +41,13 @@ impl StreamsHandler { }; let protocol = message.protocol(); - let payload = message - .to_string() - .wrap_err("failed to serialize payload")?; + let payload = message.to_string().wrap_err("failed to serialize payload")?; let peers = self.peers_to_stream.keys().cloned().collect::>(); let mut futures = FuturesUnordered::new(); for peer in peers { - let protocol_to_stream = self - .peers_to_stream - .get_mut(&peer) - .expect("stream map must exist for peer"); + let protocol_to_stream = + self.peers_to_stream.get_mut(&peer).expect("stream map must exist for peer"); let Some(stream) = protocol_to_stream.remove(&protocol) else { warn!("no stream for protocol {protocol:?} to peer {peer}"); continue; @@ -63,10 +56,7 @@ impl StreamsHandler { let payload = payload.clone(); let fut = async move { let mut writer = FramedWrite::new(stream, LinesCodec::new()); - writer - .send(payload) - .await - .wrap_err("failed to send message to peer")?; + writer.send(payload).await.wrap_err("failed to send message to peer")?; Ok::<(PeerId, libp2p::swarm::Stream), eyre::ErrReport>(( peer, writer.into_inner().into_inner(), @@ -90,10 +80,7 @@ impl StreamsHandler { } } - debug!( - "broadcasted message to {} peers", - self.peers_to_stream.len() - ); + debug!("broadcasted message to {} peers", self.peers_to_stream.len()); Ok(()) } diff --git a/crates/builder/tdx-quote-provider/src/main.rs b/crates/builder/tdx-quote-provider/src/main.rs index a820ce97..a9c74f97 100644 --- a/crates/builder/tdx-quote-provider/src/main.rs +++ b/crates/builder/tdx-quote-provider/src/main.rs @@ -77,16 +77,12 @@ async fn main() -> eyre::Result<()> { metrics_addr.parse().expect("invalid metrics address"); let builder = PrometheusBuilder::new().with_http_listener(socket_addr); - builder - .install() - .expect("failed to setup Prometheus endpoint") + builder.install().expect("failed to setup Prometheus endpoint") } // Start the server let server = Server::new(ServerConfig { - listen_addr: format!("{}:{}", args.service_host, args.service_port) - .parse() - .unwrap(), + listen_addr: format!("{}:{}", args.service_host, args.service_port).parse().unwrap(), use_mock: args.mock, mock_attestation_path: args.mock_attestation_path, }); diff --git a/crates/builder/tdx-quote-provider/src/provider.rs b/crates/builder/tdx-quote-provider/src/provider.rs index 0479edf8..27586837 100644 --- a/crates/builder/tdx-quote-provider/src/provider.rs +++ b/crates/builder/tdx-quote-provider/src/provider.rs @@ -1,4 +1,5 @@ use std::{fs::File, io::Read, sync::Arc}; + use tdx::{Tdx, device::DeviceOptions, error::TdxError}; use thiserror::Error; use tracing::info; @@ -60,9 +61,7 @@ pub struct MockAttestationProvider { impl MockAttestationProvider { pub fn new(mock_attestation_path: String) -> Self { - Self { - mock_attestation_path, - } + Self { mock_attestation_path } } } @@ -76,8 +75,7 @@ impl AttestationProvider for MockAttestationProvider { let mut file = File::open(self.mock_attestation_path.clone()) .map_err(AttestationError::ReadMockAttestationFailed)?; let mut buffer = Vec::new(); - file.read_to_end(&mut buffer) - .map_err(AttestationError::ReadMockAttestationFailed)?; + file.read_to_end(&mut buffer).map_err(AttestationError::ReadMockAttestationFailed)?; Ok(buffer) } } diff --git a/crates/builder/tdx-quote-provider/src/server.rs b/crates/builder/tdx-quote-provider/src/server.rs index b8d5e295..9123806f 100644 --- a/crates/builder/tdx-quote-provider/src/server.rs +++ b/crates/builder/tdx-quote-provider/src/server.rs @@ -61,35 +61,22 @@ impl Server { mock_attestation_path: config.mock_attestation_path.clone(), }; let quote_provider = get_attestation_provider(attestation_config); - Self { - quote_provider, - metrics: Metrics::default(), - config, - } + Self { quote_provider, metrics: Metrics::default(), config } } pub async fn listen(self) -> eyre::Result<()> { let router = Router::new() .route("/healthz", get(healthz_handler)) .route("/attest/{appdata}", get(attest_handler)) - .with_state(ServerState { - quote_provider: self.quote_provider, - metrics: self.metrics, - }); + .with_state(ServerState { quote_provider: self.quote_provider, metrics: self.metrics }); let listener = TcpListener::bind(self.config.listen_addr).await?; - info!( - message = "starting server", - address = listener.local_addr()?.to_string() - ); - - axum::serve( - listener, - router.into_make_service_with_connect_info::(), - ) - .with_graceful_shutdown(shutdown_signal()) - .await - .map_err(|e| eyre::eyre!("failed to start server: {}", e)) + info!(message = "starting server", address = listener.local_addr()?.to_string()); + + axum::serve(listener, router.into_make_service_with_connect_info::()) + .with_graceful_shutdown(shutdown_signal()) + .await + .map_err(|e| eyre::eyre!("failed to start server: {}", e)) } } @@ -137,10 +124,7 @@ async fn attest_handler( match server.quote_provider.get_attestation(report_data) { Ok(attestation) => { let duration = start.elapsed(); - server - .metrics - .attest_duration - .record(duration.as_secs_f64()); + server.metrics.attest_duration.record(duration.as_secs_f64()); Response::builder() .status(StatusCode::OK) @@ -153,9 +137,7 @@ async fn attest_handler( tracing::error!(target: "tdx_quote_provider", error = %e, "Failed to get TDX attestation"); Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from( - json!({"message": "Failed to get TDX attestation"}).to_string(), - )) + .body(Body::from(json!({"message": "Failed to get TDX attestation"}).to_string())) .unwrap() .into_response() } diff --git a/crates/builder/tdx-quote-provider/tests/simple.rs b/crates/builder/tdx-quote-provider/tests/simple.rs index afa06028..338eec4d 100644 --- a/crates/builder/tdx-quote-provider/tests/simple.rs +++ b/crates/builder/tdx-quote-provider/tests/simple.rs @@ -1,5 +1,6 @@ -use axum::body::Bytes; use std::{error::Error, net::SocketAddr, time::Duration}; + +use axum::body::Bytes; use tdx_quote_provider::server::{Server, ServerConfig}; use tokio::net::TcpListener; @@ -93,10 +94,7 @@ async fn test_mock_attest() { let response = harness.attest(report_data).await; assert!(response.is_ok()); let body = response.unwrap(); - assert_eq!( - body, - Bytes::from_static(include_bytes!("./test_data/quote.bin")) - ); + assert_eq!(body, Bytes::from_static(include_bytes!("./test_data/quote.bin"))); } #[tokio::test] diff --git a/rustfmt.toml b/rustfmt.toml index b7910780..6e800413 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,8 +4,3 @@ group_imports = "StdExternalCrate" use_small_heuristics = "Max" trailing_comma = "Vertical" use_field_init_shorthand = true - -# Ignore builder crates - they have their own formatting style -ignore = [ - "crates/builder/**", -]