Skip to content

Commit 6f119d4

Browse files
committed
test: add error path tests for block metering
Add tests for missing parent header and invalid transaction signature error cases to ensure proper error handling in meter_block.
1 parent 294a28e commit 6f119d4

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

crates/rpc/tests/meter_block.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,87 @@ fn meter_block_timing_consistency() -> eyre::Result<()> {
297297

298298
Ok(())
299299
}
300+
301+
// ============================================================================
302+
// Error Path Tests
303+
// ============================================================================
304+
305+
#[test]
306+
fn meter_block_parent_header_not_found() -> eyre::Result<()> {
307+
let harness = setup_harness()?;
308+
309+
// Create a block that references a non-existent parent
310+
let fake_parent_hash = B256::random();
311+
let header = Header {
312+
parent_hash: fake_parent_hash, // This parent doesn't exist
313+
number: 999,
314+
timestamp: harness.genesis_header_timestamp + 2,
315+
gas_limit: 30_000_000,
316+
beneficiary: Address::random(),
317+
base_fee_per_gas: Some(1),
318+
parent_beacon_block_root: Some(B256::ZERO),
319+
..Default::default()
320+
};
321+
322+
let body = OpBlockBody { transactions: vec![], ommers: vec![], withdrawals: None };
323+
let block = OpBlock::new(header, body);
324+
325+
let result = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block);
326+
327+
assert!(result.is_err(), "should fail when parent header is not found");
328+
let err = result.unwrap_err();
329+
let err_str = err.to_string();
330+
assert!(
331+
err_str.contains("Parent header not found") || err_str.contains("not found"),
332+
"error should indicate parent header not found: {}",
333+
err_str
334+
);
335+
336+
Ok(())
337+
}
338+
339+
#[test]
340+
fn meter_block_invalid_transaction_signature() -> eyre::Result<()> {
341+
use alloy_consensus::TxEip1559;
342+
use alloy_primitives::Signature;
343+
344+
let harness = setup_harness()?;
345+
346+
// Create a transaction with an invalid signature
347+
let tx = TxEip1559 {
348+
chain_id: harness.chain_spec.chain_id(),
349+
nonce: 0,
350+
gas_limit: 21_000,
351+
max_fee_per_gas: 10,
352+
max_priority_fee_per_gas: 1,
353+
to: alloy_primitives::TxKind::Call(Address::random()),
354+
value: alloy_primitives::U256::from(1000),
355+
access_list: Default::default(),
356+
input: Default::default(),
357+
};
358+
359+
// Create a signature with invalid values (all zeros is invalid for secp256k1)
360+
let invalid_signature = Signature::new(
361+
alloy_primitives::U256::ZERO,
362+
alloy_primitives::U256::ZERO,
363+
false,
364+
);
365+
366+
let signed_tx = alloy_consensus::Signed::new_unchecked(tx, invalid_signature, B256::random());
367+
let op_tx = OpTransactionSigned::Eip1559(signed_tx);
368+
369+
let block = create_block_with_transactions(&harness, vec![op_tx]);
370+
371+
let result = meter_block(harness.provider.clone(), harness.chain_spec.clone(), &block);
372+
373+
assert!(result.is_err(), "should fail when transaction has invalid signature");
374+
let err = result.unwrap_err();
375+
let err_str = err.to_string();
376+
assert!(
377+
err_str.contains("recover signer") || err_str.contains("signature"),
378+
"error should indicate signer recovery failure: {}",
379+
err_str
380+
);
381+
382+
Ok(())
383+
}

0 commit comments

Comments
 (0)