@@ -541,4 +541,89 @@ mod tests {
541541 "span missing duration_ms field"
542542 ) ;
543543 }
544+
545+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
546+ async fn try_build_drops_invalid_raw_transactions ( ) {
547+ let genesis: alloy_genesis:: Genesis =
548+ serde_json:: from_str ( include_str ! ( "../../tests/assets/genesis.json" ) )
549+ . expect ( "valid genesis" ) ;
550+ let chain_spec = Arc :: new (
551+ ChainSpecBuilder :: default ( )
552+ . chain ( reth_chainspec:: Chain :: from_id ( 1234 ) )
553+ . genesis ( genesis)
554+ . cancun_activated ( )
555+ . build ( ) ,
556+ ) ;
557+
558+ let provider = MockEthProvider :: default ( ) ;
559+ let genesis_hash = B256 :: from_slice (
560+ & hex:: decode ( "2b8bbb1ea1e04f9c9809b4b278a8687806edc061a356c7dbc491930d8e922503" )
561+ . unwrap ( ) ,
562+ ) ;
563+ let genesis_state_root = B256 :: from_slice (
564+ & hex:: decode ( "05e9954443da80d86f2104e56ffdfd98fe21988730684360104865b3dc8191b4" )
565+ . unwrap ( ) ,
566+ ) ;
567+
568+ let genesis_header = Header {
569+ state_root : genesis_state_root,
570+ number : 0 ,
571+ gas_limit : 30_000_000 ,
572+ timestamp : 1710338135 ,
573+ base_fee_per_gas : Some ( 0 ) ,
574+ excess_blob_gas : Some ( 0 ) ,
575+ blob_gas_used : Some ( 0 ) ,
576+ parent_beacon_block_root : Some ( B256 :: ZERO ) ,
577+ ..Default :: default ( )
578+ } ;
579+ provider. add_header ( genesis_hash, genesis_header. clone ( ) ) ;
580+
581+ let config = EvolvePayloadBuilderConfig :: from_chain_spec ( chain_spec. as_ref ( ) ) . unwrap ( ) ;
582+ let evm_config = EvolveEvmConfig :: new ( chain_spec) ;
583+ let evolve_builder = Arc :: new ( EvolvePayloadBuilder :: new (
584+ Arc :: new ( provider) ,
585+ evm_config,
586+ config. clone ( ) ,
587+ ) ) ;
588+
589+ let engine_builder = EvolveEnginePayloadBuilder {
590+ evolve_builder,
591+ config,
592+ pool : NoopTransactionPool :: < EvPooledTransaction > :: new ( ) ,
593+ dev_mode : false ,
594+ } ;
595+
596+ // Include garbage bytes that cannot be decoded as valid transactions.
597+ let invalid_tx = alloy_primitives:: Bytes :: from_static ( & [ 0xde , 0xad , 0xbe , 0xef ] ) ;
598+ let attrs = EvolveEnginePayloadAttributes {
599+ inner : RpcPayloadAttributes {
600+ timestamp : 1710338136 ,
601+ prev_randao : B256 :: random ( ) ,
602+ suggested_fee_recipient : Address :: random ( ) ,
603+ withdrawals : Some ( vec ! [ ] ) ,
604+ parent_beacon_block_root : Some ( B256 :: ZERO ) ,
605+ } ,
606+ transactions : Some ( vec ! [ invalid_tx] ) ,
607+ gas_limit : Some ( 30_000_000 ) ,
608+ } ;
609+ let payload_id = attrs. payload_id ( & genesis_hash) ;
610+
611+ let sealed_parent = SealedHeader :: new ( genesis_header, genesis_hash) ;
612+ let payload_config = PayloadConfig :: new ( Arc :: new ( sealed_parent) , attrs, payload_id) ;
613+ let args = BuildArguments :: new (
614+ CachedReads :: default ( ) ,
615+ None ,
616+ None ,
617+ payload_config,
618+ CancelOnDrop :: default ( ) ,
619+ None ,
620+ ) ;
621+
622+ // The build should succeed — invalid transactions are dropped, not fatal.
623+ let result = engine_builder. try_build ( args) ;
624+ assert ! (
625+ result. is_ok( ) ,
626+ "build should succeed even with invalid raw transactions, got: {result:?}"
627+ ) ;
628+ }
544629}
0 commit comments