Skip to content

Commit c19d051

Browse files
committed
test: verify payload builder drops invalid raw transactions gracefully
1 parent 0fcfd42 commit c19d051

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

crates/node/src/payload_service.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)