AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Informational 15 Bitcoin

Merge bitcoin/bitcoin#36130: test: add tests in transaction_tests.cpp covering live mutants

Public commit record

What the developer wrote

Authored by merge-script

91/100 · Strong
Merge bitcoin/bitcoin#36130: test: add tests in transaction_tests.cpp covering live mutants

5ce3a0b4aab5ad9ec710e803f88d79139b3b3c44 test: cover legacy sigops count CHECKMULTISIG inaccurately (ViniciusCestarii)
a5fc82e2b1403b7bf0f1ad494a62ccff793f99d0 test: cover enforce BIP68 to tx versions higher than 2 (ViniciusCestarii)
bba1d4150ee8d4d4b4df2b91166dff564a756c09 test: cover IsFinalTx requires every input to be SEQUENCE_FINAL (ViniciusCestarii)

Pull request description:

Kills some live mutants on tx_verify.cpp that affect consensus found with https://github.com/ViniciusCestarii/mutant-harness. They are:

<details>
<summary>tx_verify.cpp (killed by 5c35785d6ddda80d5147616342e42d759490e6b9): <code>IsFinalTx</code>: sequence loop returns on the first input instead of requiring all of them</summary>

```diff
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index e580a9d..46009a6 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -35,11 +35,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
// also check that the spending input's nSequence != SEQUENCE_FINAL,
// ensuring that an unsatisfied nLockTime value will actually cause
// IsFinalTx() to return false here:
- for (const auto& txin : tx.vin) {
- if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
- return false;
- }
- return true;
+ return std::ranges::any_of(tx.vin, [](const CTxIn& txin) { return txin.nSequence == CTxIn::SEQUENCE_FINAL; });
}

std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
```

</details>

<details>
<summary>tx_verify.cpp (killed by 3ef559d9a5cb79e4721b68427ad679d9f4f6392a): <code>CalculateSequenceLocks</code>: <code>tx.version >= 2</code> -> <code>tx.version == 2</code></summary>

```diff
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index e580a9d..0faaa55 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -54,7 +54,7 @@ std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags
int nMinHeight = -1;
int64_t nMinTime = -1;

- bool fEnforceBIP68 = tx.version >= 2 && flags & LOCKTIME_VERIFY_SEQUENCE;
+ bool fEnforceBIP68 = tx.version == 2 && flags & LOCKTIME_VERIFY_SEQUENCE;

// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to
```

</details>

<details>
<summary>tx_verify.cpp (killed by 1944eb409055d88eeaf7888b18a75289c506a943): <code>GetLegacySigOpCount</code>: <code>scriptSig.GetSigOpCount(false)</code> -> <code>GetSigOpCount(true)</code></summary>

```diff
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index e580a9d..0b98597 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -120,7 +120,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx)
unsigned int nSigOps = 0;
for (const auto& txin : tx.vin)
{
- nSigOps += txin.scriptSig.GetSigOpCount(false);
+ nSigOps += txin.scriptSig.GetSigOpCount(true);
}
for (const auto& txout : tx.vout)
{
```

</details>

Recommend reviewing per commit.

ACKs for top commit:
jeanpablojp:
tACK 5ce3a0b4aab5ad9ec710e803f88d79139b3b3c44
instagibbs:
ACK https://github.com/bitcoin/bitcoin/pull/36130/commits/5ce3a0b4aab5ad9ec710e803f88d79139b3b3c44
brunoerg:
ACK 5ce3a0b4aab5ad9ec710e803f88d79139b3b3c44
sedited:
ACK 5ce3a0b4aab5ad9ec710e803f88d79139b3b3c44

Tree-SHA512: 1f5c941638fc2907759e5a8d6faf0669b7b7d03d833b51ad675bed10585dd6b232999aa2a5ecb9e0b58db81b1ec44c9916c680e872608e4fe5ee50e71f6b82b4
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
The short version

What changed, and why it matters

This commit only adds new test cases to Bitcoin Core. It does not change any production consensus, validation, or networking code. The tests are designed to detect accidental future code changes (called 'mutants') that could break consensus rules around transaction finality, relative locktimes, and legacy signature operation counting. Because no real bug is being fixed and no live vulnerability is present, this is a defensive hardening change with no direct security impact on its own.

Recommended action

No immediate action required. Treat as routine test-coverage improvement. Reviewers may optionally verify that the new tests correctly exercise the intended consensus invariants and that they pass in CI.

Security signals we found

01

Adds regression tests for consensus-critical functions (IsFinalTx, CalculateSequenceLocks, GetLegacySigOpCount)

02

Tests target known mutation-sensitive branches in src/consensus/tx_verify.cpp

03

No changes to src/consensus/tx_verify.cpp or any other production code

04

Pull request description frames the change as test coverage for live mutants, not as a vulnerability fix

Risk score

Why this scored 15/100

Our methodology →
Potential impact 0/30
Exploitability 0/25
Stealth signal 0/15
Affected reach 0/15
Confidence 10/10
Evidence quality 5/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.