@@ -246,6 +246,8 @@ pub struct Backend {
246246 // === wallet === //
247247 capabilities : Arc < RwLock < WalletCapabilities > > ,
248248 executor_wallet : Arc < RwLock < Option < EthereumWallet > > > ,
249+ /// Disable pool balance checks
250+ disable_pool_balance_checks : bool ,
249251}
250252
251253impl Backend {
@@ -309,9 +311,9 @@ impl Backend {
309311 states = states. disk_path ( cache_path) ;
310312 }
311313
312- let ( slots_in_an_epoch, precompile_factory) = {
314+ let ( slots_in_an_epoch, precompile_factory, disable_pool_balance_checks ) = {
313315 let cfg = node_config. read ( ) . await ;
314- ( cfg. slots_in_an_epoch , cfg. precompile_factory . clone ( ) )
316+ ( cfg. slots_in_an_epoch , cfg. precompile_factory . clone ( ) , cfg . disable_pool_balance_checks )
315317 } ;
316318
317319 let ( capabilities, executor_wallet) = if odyssey {
@@ -376,6 +378,7 @@ impl Backend {
376378 mining : Arc :: new ( tokio:: sync:: Mutex :: new ( ( ) ) ) ,
377379 capabilities : Arc :: new ( RwLock :: new ( capabilities) ) ,
378380 executor_wallet : Arc :: new ( RwLock :: new ( executor_wallet) ) ,
381+ disable_pool_balance_checks,
379382 } ;
380383
381384 if let Some ( interval_block_time) = automine_block_time {
@@ -3341,22 +3344,7 @@ impl TransactionValidator for Backend {
33413344 }
33423345 }
33433346
3344- if tx. gas_limit ( ) < MIN_TRANSACTION_GAS as u64 {
3345- warn ! ( target: "backend" , "[{:?}] gas too low" , tx. hash( ) ) ;
3346- return Err ( InvalidTransactionError :: GasTooLow ) ;
3347- }
3348-
3349- // Check gas limit, iff block gas limit is set.
3350- if !env. evm_env . cfg_env . disable_block_gas_limit
3351- && tx. gas_limit ( ) > env. evm_env . block_env . gas_limit
3352- {
3353- warn ! ( target: "backend" , "[{:?}] gas too high" , tx. hash( ) ) ;
3354- return Err ( InvalidTransactionError :: GasTooHigh ( ErrDetail {
3355- detail : String :: from ( "tx.gas_limit > env.block.gas_limit" ) ,
3356- } ) ) ;
3357- }
3358-
3359- // check nonce
3347+ // Nonce validation
33603348 let is_deposit_tx =
33613349 matches ! ( & pending. transaction. transaction, TypedTransaction :: Deposit ( _) ) ;
33623350 let nonce = tx. nonce ( ) ;
@@ -3365,39 +3353,15 @@ impl TransactionValidator for Backend {
33653353 return Err ( InvalidTransactionError :: NonceTooLow ) ;
33663354 }
33673355
3368- if env. evm_env . cfg_env . spec >= SpecId :: LONDON {
3369- if tx. gas_price ( ) < env. evm_env . block_env . basefee . into ( ) && !is_deposit_tx {
3370- warn ! ( target: "backend" , "max fee per gas={}, too low, block basefee={}" , tx. gas_price( ) , env. evm_env. block_env. basefee) ;
3371- return Err ( InvalidTransactionError :: FeeCapTooLow ) ;
3372- }
3373-
3374- if let ( Some ( max_priority_fee_per_gas) , Some ( max_fee_per_gas) ) =
3375- ( tx. essentials ( ) . max_priority_fee_per_gas , tx. essentials ( ) . max_fee_per_gas )
3376- && max_priority_fee_per_gas > max_fee_per_gas
3377- {
3378- warn ! ( target: "backend" , "max priority fee per gas={}, too high, max fee per gas={}" , max_priority_fee_per_gas, max_fee_per_gas) ;
3379- return Err ( InvalidTransactionError :: TipAboveFeeCap ) ;
3380- }
3381- }
3382-
3383- // EIP-4844 Cancun hard fork validation steps
3356+ // EIP-4844 structural validation
33843357 if env. evm_env . cfg_env . spec >= SpecId :: CANCUN && tx. transaction . is_eip4844 ( ) {
3385- // Light checks first: see if the blob fee cap is too low.
3386- if let Some ( max_fee_per_blob_gas) = tx. essentials ( ) . max_fee_per_blob_gas
3387- && let Some ( blob_gas_and_price) = & env. evm_env . block_env . blob_excess_gas_and_price
3388- && max_fee_per_blob_gas < blob_gas_and_price. blob_gasprice
3389- {
3390- warn ! ( target: "backend" , "max fee per blob gas={}, too low, block blob gas price={}" , max_fee_per_blob_gas, blob_gas_and_price. blob_gasprice) ;
3391- return Err ( InvalidTransactionError :: BlobFeeCapTooLow ) ;
3392- }
3393-
33943358 // Heavy (blob validation) checks
3395- let tx = match & tx. transaction {
3359+ let blob_tx = match & tx. transaction {
33963360 TypedTransaction :: EIP4844 ( tx) => tx. tx ( ) ,
33973361 _ => unreachable ! ( ) ,
33983362 } ;
33993363
3400- let blob_count = tx . tx ( ) . blob_versioned_hashes . len ( ) ;
3364+ let blob_count = blob_tx . tx ( ) . blob_versioned_hashes . len ( ) ;
34013365
34023366 // Ensure there are blob hashes.
34033367 if blob_count == 0 {
@@ -3412,40 +3376,85 @@ impl TransactionValidator for Backend {
34123376
34133377 // Check for any blob validation errors if not impersonating.
34143378 if !self . skip_blob_validation ( Some ( * pending. sender ( ) ) )
3415- && let Err ( err) = tx . validate ( EnvKzgSettings :: default ( ) . get ( ) )
3379+ && let Err ( err) = blob_tx . validate ( EnvKzgSettings :: default ( ) . get ( ) )
34163380 {
34173381 return Err ( InvalidTransactionError :: BlobTransactionValidationError ( err) ) ;
34183382 }
34193383 }
34203384
3421- let max_cost = tx. max_cost ( ) ;
3422- let value = tx. value ( ) ;
3385+ // Balance and fee related checks
3386+ if !self . disable_pool_balance_checks {
3387+ // Gas limit validation
3388+ if tx. gas_limit ( ) < MIN_TRANSACTION_GAS as u64 {
3389+ warn ! ( target: "backend" , "[{:?}] gas too low" , tx. hash( ) ) ;
3390+ return Err ( InvalidTransactionError :: GasTooLow ) ;
3391+ }
34233392
3424- match & tx. transaction {
3425- TypedTransaction :: Deposit ( deposit_tx) => {
3426- // Deposit transactions
3427- // https://specs.optimism.io/protocol/deposits.html#execution
3428- // 1. no gas cost check required since already have prepaid gas from L1
3429- // 2. increment account balance by deposited amount before checking for sufficient
3430- // funds `tx.value <= existing account value + deposited value`
3431- if value > account. balance + U256 :: from ( deposit_tx. mint ) {
3432- warn ! ( target: "backend" , "[{:?}] insufficient balance={}, required={} account={:?}" , tx. hash( ) , account. balance + U256 :: from( deposit_tx. mint) , value, * pending. sender( ) ) ;
3433- return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3393+ // Check gas limit against block gas limit, if block gas limit is set.
3394+ if !env. evm_env . cfg_env . disable_block_gas_limit
3395+ && tx. gas_limit ( ) > env. evm_env . block_env . gas_limit
3396+ {
3397+ warn ! ( target: "backend" , "[{:?}] gas too high" , tx. hash( ) ) ;
3398+ return Err ( InvalidTransactionError :: GasTooHigh ( ErrDetail {
3399+ detail : String :: from ( "tx.gas_limit > env.block.gas_limit" ) ,
3400+ } ) ) ;
3401+ }
3402+
3403+ // EIP-1559 fee validation (London hard fork and later)
3404+ if env. evm_env . cfg_env . spec >= SpecId :: LONDON {
3405+ if tx. gas_price ( ) < env. evm_env . block_env . basefee . into ( ) && !is_deposit_tx {
3406+ warn ! ( target: "backend" , "max fee per gas={}, too low, block basefee={}" , tx. gas_price( ) , env. evm_env. block_env. basefee) ;
3407+ return Err ( InvalidTransactionError :: FeeCapTooLow ) ;
34343408 }
3409+
3410+ if let ( Some ( max_priority_fee_per_gas) , Some ( max_fee_per_gas) ) =
3411+ ( tx. essentials ( ) . max_priority_fee_per_gas , tx. essentials ( ) . max_fee_per_gas )
3412+ && max_priority_fee_per_gas > max_fee_per_gas
3413+ {
3414+ warn ! ( target: "backend" , "max priority fee per gas={}, too high, max fee per gas={}" , max_priority_fee_per_gas, max_fee_per_gas) ;
3415+ return Err ( InvalidTransactionError :: TipAboveFeeCap ) ;
3416+ }
3417+ }
3418+
3419+ // EIP-4844 blob fee validation
3420+ if env. evm_env . cfg_env . spec >= SpecId :: CANCUN
3421+ && tx. transaction . is_eip4844 ( )
3422+ && let Some ( max_fee_per_blob_gas) = tx. essentials ( ) . max_fee_per_blob_gas
3423+ && let Some ( blob_gas_and_price) = & env. evm_env . block_env . blob_excess_gas_and_price
3424+ && max_fee_per_blob_gas < blob_gas_and_price. blob_gasprice
3425+ {
3426+ warn ! ( target: "backend" , "max fee per blob gas={}, too low, block blob gas price={}" , max_fee_per_blob_gas, blob_gas_and_price. blob_gasprice) ;
3427+ return Err ( InvalidTransactionError :: BlobFeeCapTooLow ) ;
34353428 }
3436- _ => {
3437- // check sufficient funds: `gas * price + value`
3438- let req_funds = max_cost. checked_add ( value. saturating_to ( ) ) . ok_or_else ( || {
3439- warn ! ( target: "backend" , "[{:?}] cost too high" , tx. hash( ) ) ;
3440- InvalidTransactionError :: InsufficientFunds
3441- } ) ?;
3442- if account. balance < U256 :: from ( req_funds) {
3443- warn ! ( target: "backend" , "[{:?}] insufficient allowance={}, required={} account={:?}" , tx. hash( ) , account. balance, req_funds, * pending. sender( ) ) ;
3444- return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3429+
3430+ let max_cost = tx. max_cost ( ) ;
3431+ let value = tx. value ( ) ;
3432+ match & tx. transaction {
3433+ TypedTransaction :: Deposit ( deposit_tx) => {
3434+ // Deposit transactions
3435+ // https://specs.optimism.io/protocol/deposits.html#execution
3436+ // 1. no gas cost check required since already have prepaid gas from L1
3437+ // 2. increment account balance by deposited amount before checking for
3438+ // sufficient funds `tx.value <= existing account value + deposited value`
3439+ if value > account. balance + U256 :: from ( deposit_tx. mint ) {
3440+ warn ! ( target: "backend" , "[{:?}] insufficient balance={}, required={} account={:?}" , tx. hash( ) , account. balance + U256 :: from( deposit_tx. mint) , value, * pending. sender( ) ) ;
3441+ return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3442+ }
3443+ }
3444+ _ => {
3445+ // check sufficient funds: `gas * price + value`
3446+ let req_funds =
3447+ max_cost. checked_add ( value. saturating_to ( ) ) . ok_or_else ( || {
3448+ warn ! ( target: "backend" , "[{:?}] cost too high" , tx. hash( ) ) ;
3449+ InvalidTransactionError :: InsufficientFunds
3450+ } ) ?;
3451+ if account. balance < U256 :: from ( req_funds) {
3452+ warn ! ( target: "backend" , "[{:?}] insufficient allowance={}, required={} account={:?}" , tx. hash( ) , account. balance, req_funds, * pending. sender( ) ) ;
3453+ return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3454+ }
34453455 }
34463456 }
34473457 }
3448-
34493458 Ok ( ( ) )
34503459 }
34513460
0 commit comments