Skip to content

Commit 87803d4

Browse files
committed
test(zebra-consensus): assert the Orchard proof failure, not a UTXO timeout
`block_with_garbage_orchard_proofs_is_rejected` discarded the UTXO map from `mock_transparent_transfer` and sent an empty `known_utxos` for a transaction with a transparent input. The mock state never answers the lookup, so the request failed on `UTXO_LOOKUP_TIMEOUT` six minutes later and `assert!(resp.is_err())` was satisfied by that timeout: the test never reached proof verification, and would have passed with Orchard proof checking removed. It was also the slowest test in the CI profile, at 360s of the run's 623s. Pass the funding UTXO through and assert `Halo2VerificationFailed`, so the rejection under test is the one the CVE-2026-34377 advisory is about. The test now finishes in 0.7s.
1 parent b685fbe commit 87803d4

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

zebra-consensus/src/transaction/tests.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4598,7 +4598,7 @@ async fn block_with_garbage_orchard_proofs_is_rejected() {
45984598
.activation_height(&Network::Mainnet)
45994599
.expect("Nu6 activation height is specified");
46004600
let fund_height = (height - 1).expect("too small");
4601-
let (input, output, _known_utxos) = mock_transparent_transfer(
4601+
let (input, output, known_utxos) = mock_transparent_transfer(
46024602
fund_height,
46034603
true,
46044604
0,
@@ -4620,19 +4620,31 @@ async fn block_with_garbage_orchard_proofs_is_rejected() {
46204620
let garbage_tx = with_garbage_orchard_authorization(tx.clone());
46214621
assert_eq!(tx.hash(), garbage_tx.hash());
46224622

4623-
// submit garbage version as block tx, must be rejected
4623+
// Submit the garbage version as a block tx, which must be rejected.
4624+
//
4625+
// The funding UTXO has to be in `known_utxos`: the mock state never answers a lookup, so
4626+
// without it the request fails on `UTXO_LOOKUP_TIMEOUT` six minutes later and never reaches
4627+
// proof verification, which would make this test pass without checking any proof.
46244628
let resp = verifier
46254629
.clone()
46264630
.oneshot(BlockRequest {
46274631
transaction_hash: tx_hash,
46284632
transaction: Arc::new(garbage_tx),
4629-
known_utxos: Arc::new(HashMap::new()),
4633+
known_utxos: Arc::new(known_utxos),
46304634
height,
46314635
time: Utc::now(),
46324636
})
46334637
.await;
46344638

4635-
assert!(resp.is_err(), "garbage proof must be rejected");
4639+
// Buffer boxes the service error, so downcast to check the specific variant.
4640+
let err = resp.expect_err("garbage proof must be rejected");
4641+
let tx_err = err
4642+
.downcast::<TransactionError>()
4643+
.expect("error should downcast to TransactionError");
4644+
assert!(
4645+
matches!(*tx_err, TransactionError::Halo2VerificationFailed),
4646+
"expected Halo2VerificationFailed for garbage Orchard proofs; got: {tx_err:?}"
4647+
);
46364648
}
46374649

46384650
/// Regression test for the mempool-cache expiry bypass vulnerability.

0 commit comments

Comments
 (0)