Skip to content

test: pin the first two-phase cargo-mutants misses - #975

Merged
reardencode merged 2 commits into
masterfrom
test/missed-mutant-pins
Oct 10, 2026
Merged

reardencode merged 2 commits into
masterfrom
test/missed-mutant-pins

Conversation

@rearden-grok

@rearden-grok rearden-grok Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Pins the 46 misses from the first successful two-phase nightly mutants run (Actions 37895507758): fee-filter equality, getblocktxn depth 10, txid notfound, the send-budget read pause, and the comparison sites in BIP68, median time, prevout lookup, script jobs, and IBD batch meters.
  • Deletes the dead BIP34 negative-height encoder and the redundant coinbase clause beside OutPoint::is_null. The no-precompute value sum uses the money-range check.

Test plan

  • cargo test -p rbitcoin-consensus --lib -- --quiet
  • Targeted rbitcoin-net tests for the fee-filter journey, getblocktxn depth, txid notfound, and the over-budget read pause
  • Local CI except coverage (fmt, clippy -D warnings, cargo deny, ast-grep, cargo test --workspace, ci-os-smoke)
  • Required GitHub checks: qc, test, windows, macos, coverage

Made with Cursor

@average-gary average-gary left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed for correctness and performance. Nothing blocking: production always passes Some(&meta.pres) (confirm_run/phases.rs:174), so the changed no-pres branch only runs in unit tests or on a corrupt short pres. The production path performs the same; tx_to_apply drops a redundant 32-byte compare per input.

Inline: error-type mismatch plus stale comments in assemble_tx_value_out, a dead branch left in bip34_height_script, assert messages that read backwards, and a coinbase test that can't fail.

Optional, existing code outside this diff: phases.rs:190 checks meta.pres.len() == block.txdata.len() only after assemble_block_prevouts. A short pres uses the no-pres path for the extra txs before the corrupt-store error fires. Moving that check above the call means the fallback never runs in production.

Checked and fine: the over-budget ping test. V2SessionReader is cancel-safe (state lives on self.state), and over_budget is recomputed every 50ms heartbeat, so the 200ms timeout can't tear a frame. The getblocktxn depth 10/11 boundary matches peer.rs:3344.

🤖 Generated with Claude Code

return Err(ConsensusError::BadTx("negative output"));
let sats_u = o.value.to_sat();
if exceeds_max_money(sats_u) {
return Err(ConsensusError::BadTx("bad-txns-vout-toolarge"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structure gate rejects the same condition as BadBlock("bad-txns-vout-toolarge") (line 245). This branch returns BadTx, so the two paths give different reject types for the same input. Suggest BadBlock to match.

This also makes two comments stale: line 241 ("Only money-range gate") and the exceeds_max_money doc ("That cast is not a second range check"). Both need updating now that this branch range-checks too.

super::assemble_tx_value_out(&one(max_money), 0, None).unwrap(),
max_money as i64
);
assert!(super::assemble_tx_value_out(&one(max_money + 1), 0, None).is_err());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_err() would also pass on the old "negative output" / overflow errors. Suggest matches!(.., Err(ConsensusError::BadBlock("bad-txns-vout-toolarge"))) (or whatever variant line 1469 settles on), so the reject reason is pinned too.

num.push(0x00);
}
} else {
num.push(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the negative path gone this else is dead: n >= 17 here, so num is never empty. That's a fresh unkillable mutant in a PR that's killing them. abs / as i64 aren't needed anymore either. Possible form: loop on the u32, then if num.last().unwrap() & 0x80 != 0 { num.push(0) }.

assert_eq!(tx_invs(&mut eq_ann), vec![relayed.compute_wtxid()]);
assert!(
hi_ann.try_recv().is_err(),
"a fee above the filter is not announced"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message reads backwards. The peer's filter is rate + 1, so it's the filter that sits above the fee ("a filter above the fee is not announced"). The same goes for lines 376 and 389.

};
let apply = tx_to_apply(&non_cb, non_cb.compute_txid().to_byte_array()).unwrap();
assert_eq!(apply.inputs[0].prev_index, 3);
// A zero txid with a real vout is not a coinbase. `OutPoint::is_null`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removed clause (txid == 0 && vout == MAX) was exactly OutPoint::is_null(), so the deletion changes no behaviour and this case passes on both versions. The deletion is right (the original mutant was equivalent), but this test doesn't pin anything. Optional: drop it.

reardencode and others added 2 commits October 9, 2026 16:21
Fee-filter equality, getblocktxn depth 10, txid notfound, and the send-budget read pause now fail if the comparison flips. Dead BIP34 negative-height encoding and the redundant coinbase clause are gone.

Co-authored-by: Cursor <cursoragent@cursor.com>
An over-max output with no precompute row now fails as bad-txns-vout-toolarge, the same block error as the structure gate. The BIP34 height encoder no longer keeps a dead empty-body branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
@rearden-grok
rearden-grok Bot force-pushed the test/missed-mutant-pins branch from a4e10f6 to 9ea1e67 Compare October 9, 2026 23:22
@reardencode
reardencode merged commit d785ea1 into master Oct 10, 2026
18 checks passed
@rearden-grok
rearden-grok Bot deleted the test/missed-mutant-pins branch October 10, 2026 14:01
reardencode added a commit that referenced this pull request Oct 12, 2026
test: pin the misses from the two nights after #975
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants