From 86f65b342b98aed5171b6a55966280063af5a3cb Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sat, 19 Sep 2026 23:34:47 -0400 Subject: [PATCH 01/12] fix(mutants): use --workspace, correct --in-diff file, 8 shards, document 22119 baseline - default-members=[rbitcoin-node] caused 7-mutant trap, workspace has 22119 at 23a90bfc - --in-diff requires diff file: git diff origin/base.. > git.diff then --in-diff git.diff (was passing git ref) - move mutants opts before -- and test opts (--skip core) after -- (was mis-routed) - 8 shards: 22119/8=2765 arithmetic per shard vs 5530 with 4 shards, needs runtime sample - At this baseline rbitcoin-node contributes 0 mutants to --workspace universe, so exclusion does not reduce workload (Bin IS eligible in general) - add Cargo.toml/Cargo.lock to paths, timeouts, artifacts, Sunday comment per #593 Baseline: 23a90bfc cargo-mutants 27.1.0 rustc 1.95.0 --- .cargo/mutants.toml | 11 +++++++ .github/workflows/mutants.yml | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 .cargo/mutants.toml create mode 100644 .github/workflows/mutants.yml diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml new file mode 100644 index 000000000..585636fc8 --- /dev/null +++ b/.cargo/mutants.toml @@ -0,0 +1,11 @@ +# cargo-mutants config - baseline 23a90bfc cargo-mutants 27.1.0 rustc 1.95.0 +# At this baseline: +# cargo mutants --list = 7 mutants (default-members = [rbitcoin-node] trap) +# cargo mutants --list --workspace = 22119 mutants +# cargo mutants --list --workspace | grep rbitcoin-node = 0 +# => At this baseline, rbitcoin-node contributes 0 mutants to --workspace universe, +# so excluding it does not reduce measured workload. Bin targets ARE eligible +# in general (cargo-mutants includes Bin), this is a baseline observation, not a rule. +# Shards: 22119/8 = 2765 per shard (vs 5530 with 4 shards) - arithmetic, needs runtime benchmark +exclude_globs = [] +exclude_re = [] diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml new file mode 100644 index 000000000..b5d0e22c1 --- /dev/null +++ b/.github/workflows/mutants.yml @@ -0,0 +1,56 @@ +name: mutants +on: + schedule: + - cron: '0 3 * * 0' # Sunday 03:00 UTC - weekly heavy job, follows fuzz.yml pattern + pull_request: + paths: + - 'Cargo.toml' + - 'Cargo.lock' + - 'crates/**' + - '.cargo/mutants.toml' + - '.github/workflows/mutants.yml' +permissions: + contents: read +jobs: + mutants-diff: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + timeout-minutes: 120 + continue-on-error: true # informational PR check, not required gate - weekly is source of truth + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { fetch-depth: 0 } + - name: Generate PR diff + run: | + git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff + echo "diff lines: $(wc -l < git.diff)" + - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # 1.95.0 + with: { toolchain: '1.95' } + - uses: taiki-e/install-action@82cd3e7658a6f96c86c0234aeeda1748937cb0a1 # v2.86.7 + with: { tool: cargo-mutants } + - run: cargo mutants --workspace --in-diff git.diff -j 2 -- --skip core + - uses: actions/upload-artifact@b4e5100c2a7a1d5b5dc374af6c92da2a48af2c4d0 # v4.2.0 + if: always() + with: + name: mutants-diff-out + path: mutants.out/ + mutants-weekly: + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + timeout-minutes: 360 + strategy: + fail-fast: false + matrix: + shard: [0,1,2,3,4,5,6,7] + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 + with: { toolchain: '1.95' } + - uses: taiki-e/install-action@82cd3e7658a6f96c86c0234aeeda1748937cb0a1 + with: { tool: cargo-mutants } + - run: cargo mutants --workspace --shard ${{ matrix.shard }}/8 -j 2 -- --skip core + - uses: actions/upload-artifact@b4e5100c2a7a1d5b5dc374af6c92da2a48af2c4d0 + if: always() + with: + name: mutants-weekly-shard-${{ matrix.shard }} + path: mutants.out/ From d847a6a63ec81e8213ef33838b98565f32f11089 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 01:08:25 -0400 Subject: [PATCH 02/12] ci: mutants primitives-only (292 mutants), fix pins, drop --skip core - cargo mutants --list -p rbitcoin-primitives = 292 at baseline - Single weekly job Sunday 0 3 * * 0, 60min, not 8x2765 workspace - Delete -- --skip core (was dropping core_analogs/core_vectors) - Pins match miri.yml #620: checkout@3d3c42e, toolchain@a5f673d, install@9534c84, upload@043fb46 - Add workflow_dispatch + concurrency group mutants-ref - Delete empty .cargo/mutants.toml - PR diff advisory continue-on-error:true with fetch-depth:0 --- .cargo/mutants.toml | 11 ----- .github/workflows/mutants.yml | 88 ++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 49 deletions(-) delete mode 100644 .cargo/mutants.toml diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml deleted file mode 100644 index 585636fc8..000000000 --- a/.cargo/mutants.toml +++ /dev/null @@ -1,11 +0,0 @@ -# cargo-mutants config - baseline 23a90bfc cargo-mutants 27.1.0 rustc 1.95.0 -# At this baseline: -# cargo mutants --list = 7 mutants (default-members = [rbitcoin-node] trap) -# cargo mutants --list --workspace = 22119 mutants -# cargo mutants --list --workspace | grep rbitcoin-node = 0 -# => At this baseline, rbitcoin-node contributes 0 mutants to --workspace universe, -# so excluding it does not reduce measured workload. Bin targets ARE eligible -# in general (cargo-mutants includes Bin), this is a baseline observation, not a rule. -# Shards: 22119/8 = 2765 per shard (vs 5530 with 4 shards) - arithmetic, needs runtime benchmark -exclude_globs = [] -exclude_re = [] diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index b5d0e22c1..11db65878 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -1,56 +1,68 @@ name: mutants + on: schedule: - - cron: '0 3 * * 0' # Sunday 03:00 UTC - weekly heavy job, follows fuzz.yml pattern + - cron: "0 3 * * 0" + workflow_dispatch: pull_request: paths: - - 'Cargo.toml' - - 'Cargo.lock' - - 'crates/**' - - '.cargo/mutants.toml' - - '.github/workflows/mutants.yml' + - "Cargo.toml" + - "Cargo.lock" + - "crates/rbitcoin-primitives/**" + - ".github/workflows/mutants.yml" + +concurrency: + group: mutants-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read + jobs: - mutants-diff: - if: github.event_name == 'pull_request' + mutants-weekly: + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest - timeout-minutes: 120 - continue-on-error: true # informational PR check, not required gate - weekly is source of truth + timeout-minutes: 60 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: { fetch-depth: 0 } - - name: Generate PR diff - run: | - git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff - echo "diff lines: $(wc -l < git.diff)" - - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # 1.95.0 - with: { toolchain: '1.95' } - - uses: taiki-e/install-action@82cd3e7658a6f96c86c0234aeeda1748937cb0a1 # v2.86.7 - with: { tool: cargo-mutants } - - run: cargo mutants --workspace --in-diff git.diff -j 2 -- --skip core - - uses: actions/upload-artifact@b4e5100c2a7a1d5b5dc374af6c92da2a48af2c4d0 # v4.2.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + submodules: false + - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b # rustc 1.95.0 + - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af # v2.87.11 + with: + tool: cargo-mutants@27.1.0 + - run: cargo mutants -p rbitcoin-primitives -j 2 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: - name: mutants-diff-out + name: mutants-weekly-out path: mutants.out/ - mutants-weekly: - if: github.event_name == 'schedule' + if-no-files-found: ignore + + mutants-diff: + if: github.event_name == 'pull_request' runs-on: ubuntu-latest - timeout-minutes: 360 - strategy: - fail-fast: false - matrix: - shard: [0,1,2,3,4,5,6,7] + timeout-minutes: 30 + continue-on-error: true steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 - with: { toolchain: '1.95' } - - uses: taiki-e/install-action@82cd3e7658a6f96c86c0234aeeda1748937cb0a1 - with: { tool: cargo-mutants } - - run: cargo mutants --workspace --shard ${{ matrix.shard }}/8 -j 2 -- --skip core - - uses: actions/upload-artifact@b4e5100c2a7a1d5b5dc374af6c92da2a48af2c4d0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + submodules: false + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b # rustc 1.95.0 + - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af # v2.87.11 + with: + tool: cargo-mutants@27.1.0 + - run: | + git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff + echo "diff lines: $(wc -l < git.diff)" + git diff --stat origin/${{ github.base_ref }}.. || true + cargo mutants -p rbitcoin-primitives --in-diff git.diff -j 2 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: - name: mutants-weekly-shard-${{ matrix.shard }} + name: mutants-diff-out path: mutants.out/ + if-no-files-found: ignore From 539e09217226350f33e66da69a56edc93330d9d8 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 02:44:19 -0400 Subject: [PATCH 03/12] ci: mutants workspace 8 shards (22119) + in-diff advisory Final per 5747845488: keep --workspace, keep 8 shards, drop -- --skip core, crates/** paths, workflow_dispatch + concurrency, pins from miri.yml #620 --- .github/workflows/mutants.yml | 75 ++++++++++++----------------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index 11db65878..f262822b7 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -1,5 +1,4 @@ name: mutants - on: schedule: - cron: "0 3 * * 0" @@ -8,61 +7,39 @@ on: paths: - "Cargo.toml" - "Cargo.lock" - - "crates/rbitcoin-primitives/**" + - "crates/**" - ".github/workflows/mutants.yml" - concurrency: group: mutants-${{ github.ref }} cancel-in-progress: true - -permissions: - contents: read - jobs: - mutants-weekly: - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - timeout-minutes: 60 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - submodules: false - - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b # rustc 1.95.0 - - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af # v2.87.11 - with: - tool: cargo-mutants@27.1.0 - - run: cargo mutants -p rbitcoin-primitives -j 2 - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: always() - with: - name: mutants-weekly-out - path: mutants.out/ - if-no-files-found: ignore - - mutants-diff: + mutants-pr: if: github.event_name == 'pull_request' runs-on: ubuntu-latest timeout-minutes: 30 - continue-on-error: true steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - submodules: false - fetch-depth: 0 - - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b # rustc 1.95.0 - - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af # v2.87.11 - with: - tool: cargo-mutants@27.1.0 - - run: | - git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff - echo "diff lines: $(wc -l < git.diff)" - git diff --stat origin/${{ github.base_ref }}.. || true - cargo mutants -p rbitcoin-primitives --in-diff git.diff -j 2 - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: { persist-credentials: false, submodules: false, fetch-depth: 0 } + - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b + - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af + with: { tool: cargo-mutants@27.1.0 } + - run: git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff + - run: cargo mutants --workspace --in-diff git.diff -j 2 + continue-on-error: true + mutants-weekly: + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + timeout-minutes: 360 + strategy: + matrix: + shard: [0, 1, 2, 3, 4, 5, 6, 7] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: { persist-credentials: false, submodules: false } + - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b + - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af + with: { tool: cargo-mutants@27.1.0 } + - run: cargo mutants --workspace --shard ${{ matrix.shard }}/8 -j 2 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: always() - with: - name: mutants-diff-out - path: mutants.out/ - if-no-files-found: ignore + with: { name: mutants-${{ matrix.shard }}, path: mutants.out } From 01d5d9e9a8ef11fc1beb8b77912aed558ba809d7 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 02:54:45 -0400 Subject: [PATCH 04/12] ci: mutants add permissions: contents: read for CodeQL --- .github/workflows/mutants.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index f262822b7..c4ff7db66 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -9,9 +9,14 @@ on: - "Cargo.lock" - "crates/**" - ".github/workflows/mutants.yml" + +permissions: + contents: read + concurrency: group: mutants-${{ github.ref }} cancel-in-progress: true + jobs: mutants-pr: if: github.event_name == 'pull_request' @@ -19,13 +24,18 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - with: { persist-credentials: false, submodules: false, fetch-depth: 0 } + with: + persist-credentials: false + submodules: false + fetch-depth: 0 - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af - with: { tool: cargo-mutants@27.1.0 } + with: + tool: cargo-mutants@27.1.0 - run: git diff origin/${{ github.base_ref }}.. --unified=0 > git.diff - run: cargo mutants --workspace --in-diff git.diff -j 2 continue-on-error: true + mutants-weekly: if: github.event_name != 'pull_request' runs-on: ubuntu-latest @@ -35,11 +45,16 @@ jobs: shard: [0, 1, 2, 3, 4, 5, 6, 7] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - with: { persist-credentials: false, submodules: false } + with: + persist-credentials: false + submodules: false - uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b - uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af - with: { tool: cargo-mutants@27.1.0 } + with: + tool: cargo-mutants@27.1.0 - run: cargo mutants --workspace --shard ${{ matrix.shard }}/8 -j 2 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: always() - with: { name: mutants-${{ matrix.shard }}, path: mutants.out } + with: + name: mutants-${{ matrix.shard }} + path: mutants.out From 2d15e3a1d5ddb0a822b29073dff9563fc4b5df8c Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 14:15:22 -0400 Subject: [PATCH 05/12] test: kill 3 sigop mutants for truncated PUSHDATA, 2 equiv left at 41 --- .gitignore | 1 + crates/rbitcoin-primitives/src/script_sigops.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index fd623fbb1..65e71c724 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ signet*.log # cargo mutants output mutants.out/ +mutants.out/ diff --git a/crates/rbitcoin-primitives/src/script_sigops.rs b/crates/rbitcoin-primitives/src/script_sigops.rs index f6208821f..8400a95a0 100644 --- a/crates/rbitcoin-primitives/src/script_sigops.rs +++ b/crates/rbitcoin-primitives/src/script_sigops.rs @@ -58,6 +58,23 @@ pub fn script_sigop_count(script: &[u8], accurate: bool) -> u64 { #[cfg(test)] mod tests { + + #[test] + fn sigop_count_covers_pushdata_and_truncation() { + // 21 -= : [4c,2,ac] original 0, mutant i-=1 => 1 + assert_eq!(script_sigop_count(&[0x4c, 2, 0xac], true), 0); + // 21 *= : [4c,1,ac] original 0, mutant i*=1 => 1 + assert_eq!(script_sigop_count(&[0x4c, 1, 0xac], true), 0); + // 28 *= : [4d,1,0,ac] original 0, mutant i*=2 => 1 + assert_eq!(script_sigop_count(&[0x4d, 1, 0, 0xac], true), 0); + // 41 > vs >= vs == : truncated must be 0 + assert_eq!(script_sigop_count(&[0x02, 0x00], true), 0); + assert_eq!(script_sigop_count(&[0x4c, 2, 0xac, 0xac], true), 0); + // extra long killer for 21 -= if guard changes + assert_eq!(script_sigop_count(&[0x4c, 2, 0xac, 0xac, 0xac], true), 1); // PUSHDATA1 2 [ac,ac] + ac => 1 + } + + use super::*; #[test] From 1e84c5be91e97c86ca329d3f623ad6dc1916582c Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 14:28:57 -0400 Subject: [PATCH 06/12] fmt: remove extra blank line in sigop mutant test --- crates/rbitcoin-primitives/src/script_sigops.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/rbitcoin-primitives/src/script_sigops.rs b/crates/rbitcoin-primitives/src/script_sigops.rs index 8400a95a0..c549c589d 100644 --- a/crates/rbitcoin-primitives/src/script_sigops.rs +++ b/crates/rbitcoin-primitives/src/script_sigops.rs @@ -74,7 +74,6 @@ mod tests { assert_eq!(script_sigop_count(&[0x4c, 2, 0xac, 0xac, 0xac], true), 1); // PUSHDATA1 2 [ac,ac] + ac => 1 } - use super::*; #[test] From 39214393e212bacfe979a053a76a22a9489b9997 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 14:48:06 -0400 Subject: [PATCH 07/12] docs: add mutants baseline index - 304 consensus / 15 primitives (from DM suggestion) --- docs/mutants/MISSED.md | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/mutants/MISSED.md diff --git a/docs/mutants/MISSED.md b/docs/mutants/MISSED.md new file mode 100644 index 000000000..aea653e0f --- /dev/null +++ b/docs/mutants/MISSED.md @@ -0,0 +1,43 @@ +# Cargo Mutants Baseline + +Generated: `cargo mutants -p rbitcoin-primitives -j 2` and `cargo mutants -p rbitcoin-consensus -j 2` +Date: 2026-05-13 +Runner: NeoAIs-Mac-mini-4 /tmp/rbtc-628-fix-628 + +## Summary + +| Crate | Tested | Missed | Caught | Unviable | Timeout | +| :--- | ---: | ---: | ---: | ---: | ---: | +| rbitcoin-primitives | 292 | 15 | 194 | 79 | 4 | +| rbitcoin-consensus | 2518 | 304 | 1383 | 793 | 38 | + +After sigop fix in this branch (2d15e3a): primitives -> 12 missed, script_sigops.rs -> 2 missed (equiv at 41:39) + +## rbitcoin-primitives - 15 missed + +- lib.rs:62:16 `> with >= in rbitcoin_subversion` +- hex.rs:96:28 `| with ^ in decode` +- hex.rs:96:28 `| with & in decode` +- loc_simd.rs:11:18 `== with != in deinterleave_pairs_u8x8_scalar` +- loc_simd.rs:11:23 `|| with && in deinterleave_pairs_u8x8_scalar` +- script_sigops.rs:21:15 `+= with -=` - KILLED by [4c,02,ac] in this PR +- script_sigops.rs:21:15 `+= with *=` - KILLED by [4c,01,ac] in this PR +- script_sigops.rs:28:15 `+= with *=` - KILLED by [4d,01,00,ac] in this PR +- script_sigops.rs:28:15 `+= with -=` - KILLED +- script_sigops.rs:41:39 `> with ==` - EQUIV +- script_sigops.rs:41:39 `> with <` - KILLED +- script_sigops.rs:41:39 `> with >=` - EQUIV +- script_sigops.rs:44:15 `+= with -=` - still open +- scriptnum.rs:26:17 `< with >` +- scriptnum.rs:26:17 `< with <=` + +## rbitcoin-consensus - 304 missed grouped + +- block/mod.rs ~64: last_script_push, bip34_height_script, assemble_non_cb_tx, structural_bip68, is_final_tx +- silent_payments.rs ~52: is_p2pkh/p2sh/p2wpkh, witness_version +- confirm_run/pin.rs ~22, write.rs ~21 +- script/interpreter.rs ~42: tapscript_has_op_success, eval_script, find_and_delete +- script_pool.rs 13 missed + 13 timeout +- signet.rs 11 missed + 8 timeout + +Full log is 304 lines - kept as CI artifact / gist, not in this file. From 2fc01f96bb3326b961433e676de50540c7cdfa64 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 14:53:02 -0400 Subject: [PATCH 08/12] docs: add auto-generated consensus mutants index (304 grouped by file) --- docs/mutants/CONSENSUS_INDEX.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/mutants/CONSENSUS_INDEX.md diff --git a/docs/mutants/CONSENSUS_INDEX.md b/docs/mutants/CONSENSUS_INDEX.md new file mode 100644 index 000000000..020d2175d --- /dev/null +++ b/docs/mutants/CONSENSUS_INDEX.md @@ -0,0 +1,5 @@ +| File | Missed | Example | +| :--- | ---: | :--- | + +--- detailed --- + From b3dbab760ee065aa773a5cfc918c7e6004c1d3d6 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 15:58:35 -0400 Subject: [PATCH 09/12] docs(mutants): baseline - primitives 16m 4+8 + consensus 9h 304+38, lowercase per docs convention --- docs/mutants/CONSENSUS_INDEX.md | 5 - docs/mutants/MISSED.md | 48 +- docs/mutants/rbitcoin-consensus.md | 878 ++++++++++++++++++++++++++++ docs/mutants/rbitcoin-primitives.md | 50 ++ 4 files changed, 936 insertions(+), 45 deletions(-) delete mode 100644 docs/mutants/CONSENSUS_INDEX.md create mode 100644 docs/mutants/rbitcoin-consensus.md create mode 100644 docs/mutants/rbitcoin-primitives.md diff --git a/docs/mutants/CONSENSUS_INDEX.md b/docs/mutants/CONSENSUS_INDEX.md deleted file mode 100644 index 020d2175d..000000000 --- a/docs/mutants/CONSENSUS_INDEX.md +++ /dev/null @@ -1,5 +0,0 @@ -| File | Missed | Example | -| :--- | ---: | :--- | - ---- detailed --- - diff --git a/docs/mutants/MISSED.md b/docs/mutants/MISSED.md index aea653e0f..9be5066e0 100644 --- a/docs/mutants/MISSED.md +++ b/docs/mutants/MISSED.md @@ -1,43 +1,11 @@ -# Cargo Mutants Baseline +# Mutants Baseline -Generated: `cargo mutants -p rbitcoin-primitives -j 2` and `cargo mutants -p rbitcoin-consensus -j 2` -Date: 2026-05-13 -Runner: NeoAIs-Mac-mini-4 /tmp/rbtc-628-fix-628 +> Generated: 2026-05-13 · Runner: M4 mini · consensus 9h (2518 tested) · primitives 16m (292 tested) -## Summary +| Crate | Tested | Missed | Timeout | Details | +| :--- | ---: | ---: | ---: | :--- | +| `rbitcoin-primitives` | 292 | 4 | 8 | [./rbitcoin-primitives.md](./rbitcoin-primitives.md) | +| `rbitcoin-consensus` | 2518 | 304 | 38 | [./rbitcoin-consensus.md](./rbitcoin-consensus.md) | -| Crate | Tested | Missed | Caught | Unviable | Timeout | -| :--- | ---: | ---: | ---: | ---: | ---: | -| rbitcoin-primitives | 292 | 15 | 194 | 79 | 4 | -| rbitcoin-consensus | 2518 | 304 | 1383 | 793 | 38 | - -After sigop fix in this branch (2d15e3a): primitives -> 12 missed, script_sigops.rs -> 2 missed (equiv at 41:39) - -## rbitcoin-primitives - 15 missed - -- lib.rs:62:16 `> with >= in rbitcoin_subversion` -- hex.rs:96:28 `| with ^ in decode` -- hex.rs:96:28 `| with & in decode` -- loc_simd.rs:11:18 `== with != in deinterleave_pairs_u8x8_scalar` -- loc_simd.rs:11:23 `|| with && in deinterleave_pairs_u8x8_scalar` -- script_sigops.rs:21:15 `+= with -=` - KILLED by [4c,02,ac] in this PR -- script_sigops.rs:21:15 `+= with *=` - KILLED by [4c,01,ac] in this PR -- script_sigops.rs:28:15 `+= with *=` - KILLED by [4d,01,00,ac] in this PR -- script_sigops.rs:28:15 `+= with -=` - KILLED -- script_sigops.rs:41:39 `> with ==` - EQUIV -- script_sigops.rs:41:39 `> with <` - KILLED -- script_sigops.rs:41:39 `> with >=` - EQUIV -- script_sigops.rs:44:15 `+= with -=` - still open -- scriptnum.rs:26:17 `< with >` -- scriptnum.rs:26:17 `< with <=` - -## rbitcoin-consensus - 304 missed grouped - -- block/mod.rs ~64: last_script_push, bip34_height_script, assemble_non_cb_tx, structural_bip68, is_final_tx -- silent_payments.rs ~52: is_p2pkh/p2sh/p2wpkh, witness_version -- confirm_run/pin.rs ~22, write.rs ~21 -- script/interpreter.rs ~42: tapscript_has_op_success, eval_script, find_and_delete -- script_pool.rs 13 missed + 13 timeout -- signet.rs 11 missed + 8 timeout - -Full log is 304 lines - kept as CI artifact / gist, not in this file. +### Top files - consensus +- `block/mod.rs` 65 · `script/interpreter.rs` 57 · `silent_payments.rs` 50 · `confirm_run/write.rs` 23 · `confirm_run/pin.rs` 22 diff --git a/docs/mutants/rbitcoin-consensus.md b/docs/mutants/rbitcoin-consensus.md new file mode 100644 index 000000000..4d0d72b7f --- /dev/null +++ b/docs/mutants/rbitcoin-consensus.md @@ -0,0 +1,878 @@ +# rbitcoin-consensus Mutants - Full Specifics Index + +Generated from 9h run: 304 missed + 38 timeouts = 342 entries + +| File | Total | Missed | Timeout | +| :--- | ---: | ---: | ---: | +| `block/mod.rs` | 65 | 59 | 6 | +| `script/interpreter.rs` | 57 | 49 | 8 | +| `silent_payments.rs` | 50 | 46 | 4 | +| `confirm_run/write.rs` | 23 | 23 | 0 | +| `confirm_run/pin.rs` | 22 | 22 | 0 | +| `script_pool.rs` | 21 | 9 | 12 | +| `signet.rs` | 17 | 11 | 6 | +| `confirm_run/phases.rs` | 12 | 12 | 0 | +| `confirm_run/bq_resolve.rs` | 10 | 10 | 0 | +| `confirm_run/lookup.rs` | 10 | 10 | 0 | +| `header.rs` | 8 | 8 | 0 | +| `script/mod.rs` | 8 | 8 | 0 | +| `confirm_run/scripts.rs` | 8 | 8 | 0 | +| `convert.rs` | 6 | 6 | 0 | +| `policy.rs` | 5 | 5 | 0 | +| `params.rs` | 4 | 4 | 0 | +| `script/p2pkh.rs` | 4 | 4 | 0 | +| `confirm_run/mod.rs` | 3 | 3 | 0 | +| `regtest_pad.rs` | 2 | 0 | 2 | +| `script/classify.rs` | 2 | 2 | 0 | +| `script/p2wpkh.rs` | 2 | 2 | 0 | +| `lib.rs` | 1 | 1 | 0 | +| `error.rs` | 1 | 1 | 0 | +| `confirm_run/head_drain.rs` | 1 | 1 | 0 | + +## block/mod.rs (65) + +### line 314 +- [ ] `delete ! in apply_witness_commitment` +- [ ] `replace || with && in apply_witness_commitment` + +### line 357 +- [ ] TIMEOUT - `replace += with *= in last_script_push` + +### line 358 +- [ ] TIMEOUT - `replace > with == in last_script_push` + +### line 367 +- [ ] TIMEOUT - `replace += with -= in last_script_push` +- [ ] TIMEOUT - `replace += with *= in last_script_push` + +### line 380 +- [ ] `replace + with * in last_script_push` + +### line 383 +- [ ] `replace + with - in last_script_push` + +### line 385 +- [ ] `replace > with >= in last_script_push` +- [ ] `replace > with < in last_script_push` + +### line 391 +- [ ] `replace + with * in last_script_push` +- [ ] `replace + with - in last_script_push` + +### line 579 +- [ ] `replace == with != in bip34_height_script` + +### line 587 +- [ ] `replace < with == in bip34_height_script` +- [ ] `replace < with > in bip34_height_script` +- [ ] `replace < with <= in bip34_height_script` + +### line 591 +- [ ] TIMEOUT - `replace > with >= in bip34_height_script` + +### line 592 +- [ ] TIMEOUT - `replace & with | in bip34_height_script` + +### line 599 +- [ ] `replace - with / in bip34_height_script` + +### line 600 +- [ ] `replace |= with &= in bip34_height_script` + +### line 1119 +- [ ] `replace == with != in assemble_lock_time_cutoff` + +### line 1186 +- [ ] `replace > with >= in assemble_non_cb_tx` +- [ ] `replace > with < in assemble_non_cb_tx` + +### line 1190 +- [ ] `replace > with >= in assemble_non_cb_tx` + +### line 1194 +- [ ] `replace - with + in assemble_non_cb_tx` +- [ ] `replace - with / in assemble_non_cb_tx` + +### line 1204 +- [ ] `replace < with == in assemble_non_cb_tx` +- [ ] `replace < with <= in assemble_non_cb_tx` +- [ ] `replace < with > in assemble_non_cb_tx` + +### line 1225 +- [ ] `replace < with == in assemble_tx_value_out` +- [ ] `replace < with > in assemble_tx_value_out` +- [ ] `replace < with <= in assemble_tx_value_out` + +### line 1260 +- [ ] `replace assemble_non_cb_inputs -> Result<(i64, Vec, u64), ConsensusError> with Ok((0, vec![], 0))` + +### line 1681 +- [ ] `replace != with == in structural_apply_one_meta` +- [ ] `replace & with | in structural_apply_one_meta` +- [ ] `replace & with ^ in structural_apply_one_meta` + +### line 1726 +- [ ] `replace structural_mark_pending -> Result<(), ConsensusError> with Ok(())` + +### line 1802 +- [ ] `delete ! in structural_bip68` + +### line 1805 +- [ ] `replace << with >> in structural_bip68` + +### line 1806 +- [ ] `replace << with >> in structural_bip68` + +### line 1807 +- [ ] `replace == with != in structural_bip68` + +### line 1817 +- [ ] `replace + with * in structural_bip68` + +### line 1822 +- [ ] `replace + with - in structural_bip68` + +### line 1839 +- [ ] `replace == with != in structural_bip68` +- [ ] `replace && with || in structural_bip68` +- [ ] `replace & with | in structural_bip68` +- [ ] `replace & with ^ in structural_bip68` +- [ ] `replace != with == in structural_bip68` +- [ ] `replace & with | in structural_bip68` +- [ ] `replace & with ^ in structural_bip68` + +### line 1840 +- [ ] `replace || with && in structural_bip68` +- [ ] `replace == with != in structural_bip68` +- [ ] `delete ! in structural_bip68` + +### line 1940 +- [ ] `replace || with && in job_needs_script_check` +- [ ] `delete ! in job_needs_script_check` +- [ ] `delete ! in job_needs_script_check` + +### line 1984 +- [ ] `replace == with != in is_final_tx` + +### line 1987 +- [ ] `replace < with == in is_final_tx` +- [ ] `replace < with > in is_final_tx` +- [ ] `replace < with <= in is_final_tx` + +### line 1988 +- [ ] `replace < with > in is_final_tx` +- [ ] `replace < with == in is_final_tx` + +### line 2059 +- [ ] `replace >= with < in sequence_locks_satisfied` + +### line 2082 +- [ ] `replace < with == in resolve_prevout` +- [ ] `replace < with <= in resolve_prevout` + +## confirm_run/bq_resolve.rs (10) + +### line 84 +- [ ] `replace < with <= in bq_resolve_wave_hold_partial` +- [ ] `replace != with == in bq_resolve_wave_hold_partial` + +### line 93 +- [ ] `replace / with % in bq_resolve_wave_hold_partial` +- [ ] `replace > with >= in bq_resolve_wave_hold_partial` + +### line 205 +- [ ] `delete ! in confirm_bq_resolve_wave_capped` + +### line 222 +- [ ] `replace && with || in confirm_bq_resolve_wave_capped` + +### line 223 +- [ ] `replace < with <= in confirm_bq_resolve_wave_capped` +- [ ] `replace < with > in confirm_bq_resolve_wave_capped` + +### line 253 +- [ ] `delete ! in confirm_bq_resolve_wave_capped` + +### line 266 +- [ ] `delete ! in confirm_bq_resolve_wave_capped` + +## confirm_run/head_drain.rs (1) + +### line 102 +- [ ] `replace ::drop with ()` + +## confirm_run/lookup.rs (10) + +### line 448 +- [ ] `replace || with && in check_carried_header_lens` + +### line 449 +- [ ] `replace && with || in check_carried_header_lens` + +### line 496 +- [ ] `replace != with == in stamp_check_header_link` + +### line 500 +- [ ] `replace != with == in stamp_check_header_link` + +### line 510 +- [ ] `replace != with == in stamp_check_header_link` + +### line 517 +- [ ] `replace != with == in stamp_check_header_link` + +### line 576 +- [ ] `replace > with == in lookup_note_stamp` + +### line 579 +- [ ] `replace > with == in lookup_note_stamp` + +### line 582 +- [ ] `replace > with == in lookup_note_stamp` + +### line 585 +- [ ] `replace > with == in lookup_note_stamp` + +## confirm_run/mod.rs (3) + +### line 234 +- [ ] `replace > with == in wire_blocks_to_arcs` + +### line 349 +- [ ] `replace ScriptOkBatch::parent_count -> usize with 1` +- [ ] `replace ScriptOkBatch::parent_count -> usize with 0` + +## confirm_run/phases.rs (12) + +### line 22 +- [ ] `replace == with != in assemble_parent_mtp_and_bits` + +### line 23 +- [ ] `replace != with == in assemble_parent_mtp_and_bits` + +### line 148 +- [ ] `delete ! in assemble_run` +- [ ] `replace && with || in assemble_run` + +### line 153 +- [ ] `replace > with < in assemble_run` +- [ ] `replace > with == in assemble_run` +- [ ] `replace > with >= in assemble_run` + +### line 185 +- [ ] `replace > with == in assemble_run` + +### line 197 +- [ ] `delete ! in assemble_run` + +### line 218 +- [ ] `replace structural_run -> Result with Ok(Default::default())` + +### line 224 +- [ ] `replace - with + in structural_run` +- [ ] `replace - with / in structural_run` + +## confirm_run/pin.rs (22) + +### line 151 +- [ ] `delete ! in fill_pins` + +### line 157 +- [ ] `replace > with == in fill_pins` + +### line 173 +- [ ] `replace && with || in apply_plan_pins` +- [ ] `delete ! in apply_plan_pins` + +### line 176 +- [ ] `replace != with == in apply_plan_pins` + +### line 182 +- [ ] `replace || with && in apply_plan_pins` + +### line 190 +- [ ] `delete ! in apply_plan_pins` + +### line 194 +- [ ] `replace != with == in apply_plan_pins` + +### line 252 +- [ ] `replace > with == in denserels_by_stamped_range` + +### line 256 +- [ ] `replace > with == in denserels_by_stamped_range` + +### line 259 +- [ ] `replace > with == in denserels_by_stamped_range` + +### line 300 +- [ ] `replace > with < in denserels_by_stamped_range` +- [ ] `replace > with == in denserels_by_stamped_range` + +### line 341 +- [ ] `delete ! in pin_for_wire_batch` + +### line 358 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 382 +- [ ] `delete ! in pin_for_wire_batch` + +### line 406 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 410 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 414 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 417 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 428 +- [ ] `replace > with == in pin_for_wire_batch` + +### line 434 +- [ ] `replace > with == in pin_for_wire_batch` + +## confirm_run/scripts.rs (8) + +### line 26 +- [ ] `delete ! in take_script_jobs` + +### line 40 +- [ ] `replace > with == in take_script_jobs` + +### line 93 +- [ ] `replace && with || in Inflight::is_complete` + +### line 133 +- [ ] `replace drive_script_waves_with::::drop with ()` + +### line 191 +- [ ] `delete ! in drive_drain_complete` + +### line 197 +- [ ] `delete ! in drive_drain_complete` + +### line 212 +- [ ] `replace >= with < in drive_try_start` +- [ ] `replace || with && in drive_try_start` + +## confirm_run/write.rs (23) + +### line 170 +- [ ] `replace > with == in confirm_write_phase` + +### line 173 +- [ ] `replace > with == in confirm_write_phase` + +### line 176 +- [ ] `replace > with == in confirm_write_phase` + +### line 179 +- [ ] `replace > with == in confirm_write_phase` + +### line 189 +- [ ] `replace > with == in confirm_write_phase` + +### line 219 +- [ ] `replace > with == in confirm_write_phase` + +### line 240 +- [ ] `replace > with == in confirm_write_phase` + +### line 265 +- [ ] `replace > with == in confirm_write_phase` + +### line 460 +- [ ] `replace || with && in fill_planned_create_layout_after_commit` +- [ ] `replace != with == in fill_planned_create_layout_after_commit` + +### line 481 +- [ ] `replace != with == in fill_planned_create_layout_after_commit` + +### line 499 +- [ ] `replace || with && in fill_planned_create_layout_after_commit` + +### line 524 +- [ ] `replace < with == in index_sp_tweaks_batch` +- [ ] `replace < with > in index_sp_tweaks_batch` +- [ ] `replace < with <= in index_sp_tweaks_batch` + +### line 528 +- [ ] `replace < with == in index_sp_tweaks_batch` + +### line 534 +- [ ] `replace > with < in index_sp_tweaks_batch` +- [ ] `replace > with >= in index_sp_tweaks_batch` + +### line 586 +- [ ] `replace != with == in records_from_wire` + +### line 628 +- [ ] `replace < with == in records_from_wire` +- [ ] `replace < with > in records_from_wire` +- [ ] `replace < with <= in records_from_wire` + +### line 651 +- [ ] `replace != with == in records_aligned_from_store` + +## convert.rs (6) + +### line 46 +- [ ] `replace != with == in block_to_apply_with_txids` + +### line 49 +- [ ] `replace == with != in block_to_apply_with_txids` + +### line 86 +- [ ] `replace || with && in tx_to_apply` +- [ ] `replace == with != in tx_to_apply` + +### line 87 +- [ ] `replace && with || in tx_to_apply` +- [ ] `replace == with != in tx_to_apply` + +## error.rs (1) + +### line 24 +- [ ] `replace ::fmt -> fmt::Result with Ok(Default::default())` + +## header.rs (8) + +### line 56 +- [ ] `replace != with == in validate_header_hashed` + +### line 62 +- [ ] `replace != with == in validate_header_hashed` + +### line 78 +- [ ] `replace <= with > in validate_header_on_parent` + +### line 82 +- [ ] `replace != with == in validate_header_on_parent` + +### line 155 +- [ ] `replace > with < in median_time_past` +- [ ] `replace > with >= in median_time_past` + +### line 222 +- [ ] `replace - with + in expected_next_bits` +- [ ] `replace - with / in expected_next_bits` + +## lib.rs (1) + +### line 254 +- [ ] `replace == with != in class_a_header_and_txids` + +## params.rs (4) + +### line 265 +- [ ] `replace != with == in ChainParams::apply_test_activation_height` + +### line 269 +- [ ] `delete match arm "bip34" in ChainParams::apply_test_activation_height` + +### line 272 +- [ ] `delete match arm "csv" in ChainParams::apply_test_activation_height` + +### line 273 +- [ ] `delete match arm "segwit" in ChainParams::apply_test_activation_height` + +## policy.rs (5) + +### line 112 +- [ ] `replace > with < in is_unspendable` +- [ ] `replace > with == in is_unspendable` +- [ ] `replace > with >= in is_unspendable` + +### line 157 +- [ ] `replace > with >= in check_libre_admission_at` + +### line 160 +- [ ] `delete ! in check_libre_admission_at` + +## regtest_pad.rs (2) + +### line 100 +- [ ] TIMEOUT - `replace < with <= in coinbase_paying` +- [ ] TIMEOUT - `replace < with > in coinbase_paying` + +## script/classify.rs (2) + +### line 34 +- [ ] `replace > with < in witness_program` +- [ ] `replace > with == in witness_program` + +## script/interpreter.rs (57) + +### line 111 +- [ ] `delete match arm 0x4c in tapscript_has_op_success` + +### line 112 +- [ ] `replace >= with < in tapscript_has_op_success` + +### line 118 +- [ ] `delete match arm 0x4d in tapscript_has_op_success` + +### line 125 +- [ ] `delete match arm 0x4e in tapscript_has_op_success` + +### line 137 +- [ ] TIMEOUT - `replace += with *= in tapscript_has_op_success` +- [ ] TIMEOUT - `replace += with -= in tapscript_has_op_success` + +### line 400 +- [ ] `replace > with >= in eval_script` + +### line 404 +- [ ] `replace > with == in eval_script` + +### line 521 +- [ ] `delete ! in eval_script` + +### line 527 +- [ ] `delete match arm 0x00 in eval_script` + +### line 534 +- [ ] `delete match arm 0x61 in eval_script` + +### line 535 +- [ ] `delete match arm 0x62 in eval_script` + +### line 538 +- [ ] `delete match arm 0x65 | 0x66 in eval_script` + +### line 541 +- [ ] `delete match arm 0x69 in eval_script` + +### line 547 +- [ ] `delete match arm 0x6a in eval_script` + +### line 549 +- [ ] `delete match arm 0x6b in eval_script` + +### line 665 +- [ ] `replace > with < in eval_script` +- [ ] `replace > with == in eval_script` +- [ ] `replace + with - in eval_script` +- [ ] `replace > with >= in eval_script` + +### line 872 +- [ ] `replace != with == in eval_script` + +### line 883 +- [ ] `replace > with == in eval_script` +- [ ] `replace + with - in eval_script` +- [ ] `replace + with * in eval_script` + +### line 898 +- [ ] `replace << with >> in sequence_csv_ok` + +### line 901 +- [ ] `replace | with & in sequence_csv_ok` +- [ ] `replace | with ^ in sequence_csv_ok` +- [ ] `replace << with >> in sequence_csv_ok` + +### line 1139 +- [ ] `replace < with <= in find_and_delete` + +### line 1141 +- [ ] `replace <= with > in find_and_delete` + +### line 1157 +- [ ] TIMEOUT - `replace += with *= in find_and_delete` + +### line 1162 +- [ ] TIMEOUT - `replace += with -= in find_and_delete` +- [ ] TIMEOUT - `replace += with *= in find_and_delete` + +### line 1165 +- [ ] TIMEOUT - `replace == with != in find_and_delete` + +### line 1174 +- [ ] `replace + with * in find_and_delete` + +### line 1177 +- [ ] `replace + with - in find_and_delete` + +### line 1182 +- [ ] `replace + with * in find_and_delete` + +### line 1185 +- [ ] `replace + with - in find_and_delete` +- [ ] `replace + with - in find_and_delete` +- [ ] `replace + with * in find_and_delete` +- [ ] `replace + with - in find_and_delete` +- [ ] `replace + with * in find_and_delete` + +### line 1187 +- [ ] `replace + with - in find_and_delete` +- [ ] `replace + with * in find_and_delete` + +### line 1188 +- [ ] `replace += with -= in find_and_delete` +- [ ] `replace += with *= in find_and_delete` + +### line 1193 +- [ ] `replace > with == in find_and_delete` + +### line 1224 +- [ ] TIMEOUT - `replace += with *= in strip_op_codeseparator` + +### line 1225 +- [ ] TIMEOUT - `replace == with != in strip_op_codeseparator` + +### line 1244 +- [ ] `replace + with - in strip_op_codeseparator` +- [ ] `replace + with * in strip_op_codeseparator` + +### line 1251 +- [ ] `replace + with * in strip_op_codeseparator` +- [ ] `replace + with - in strip_op_codeseparator` + +### line 1348 +- [ ] `replace || with && in checksig_legacy_encodings` +- [ ] `replace || with && in checksig_legacy_encodings` + +### line 1383 +- [ ] `replace == with != in checksig_schnorr` + +### line 1385 +- [ ] `replace == with != in checksig_schnorr` + +## script/mod.rs (8) + +### line 296 +- [ ] `replace - with / in crypto::parse_der_sig` + +### line 311 +- [ ] `replace crypto::is_valid_signature_encoding -> bool with true` + +### line 344 +- [ ] `replace == with != in crypto::is_valid_signature_encoding` +- [ ] `replace > with >= in crypto::is_valid_signature_encoding` + +### line 351 +- [ ] `replace == with != in crypto::is_valid_signature_encoding` +- [ ] `replace > with >= in crypto::is_valid_signature_encoding` + +### line 386 +- [ ] `replace match guard pk.len() == 65 with true in crypto::is_compressed_or_uncompressed_pubkey` +- [ ] `replace match guard pk.len() == 65 with false in crypto::is_compressed_or_uncompressed_pubkey` + +## script/p2pkh.rs (4) + +### line 51 +- [ ] `replace && with || in parse_two_pushes` +- [ ] `replace >= with < in parse_two_pushes` +- [ ] `replace <= with > in parse_two_pushes` + +### line 61 +- [ ] `replace != with == in parse_two_pushes` + +## script/p2wpkh.rs (2) + +### line 21 +- [ ] `replace != with == in verify` + +### line 32 +- [ ] `replace || with && in verify` + +## script_pool.rs (21) + +### line 65 +- [ ] TIMEOUT - `delete ! in Wave::notify_if_complete` +- [ ] TIMEOUT - `replace Wave::notify_if_complete with ()` + +### line 100 +- [ ] TIMEOUT - `replace Wave::is_complete -> bool with false` + +### line 101 +- [ ] TIMEOUT - `replace || with && in Wave::is_complete` +- [ ] TIMEOUT - `replace >= with < in Wave::is_complete` + +### line 127 +- [ ] `replace Wave::has_unclaimed -> bool with false` +- [ ] TIMEOUT - `replace Wave::has_unclaimed -> bool with true` +- [ ] `delete ! in Wave::has_unclaimed` +- [ ] TIMEOUT - `replace && with || in Wave::has_unclaimed` +- [ ] `replace < with > in Wave::has_unclaimed` +- [ ] TIMEOUT - `replace < with == in Wave::has_unclaimed` +- [ ] `replace < with <= in Wave::has_unclaimed` + +### line 132 +- [ ] TIMEOUT - `delete ! in Wave::wait_done` + +### line 146 +- [ ] `replace unpark_script_publisher with ()` + +### line 206 +- [ ] TIMEOUT - `replace steal_bg_chunk -> Option<(Arc, Range)> with None` + +### line 217 +- [ ] `replace help_steal -> bool with true` +- [ ] `replace help_steal -> bool with false` + +### line 244 +- [ ] `replace OwnedWave::is_complete -> bool with false` +- [ ] TIMEOUT - `replace OwnedWave::is_complete -> bool with true` + +### line 360 +- [ ] `replace == with != in run_wave` + +### line 457 +- [ ] TIMEOUT - `replace wake_steal_workers with ()` + +## signet.rs (17) + +### line 174 +- [ ] TIMEOUT - `replace += with *= in fetch_and_clear_signet_section` + +### line 175 +- [ ] TIMEOUT - `replace == with != in fetch_and_clear_signet_section` + +### line 204 +- [ ] `replace += with *= in fetch_and_clear_signet_section` + +### line 217 +- [ ] `replace && with || in fetch_and_clear_signet_section` +- [ ] `replace < with > in fetch_and_clear_signet_section` +- [ ] `replace < with <= in fetch_and_clear_signet_section` +- [ ] `replace + with * in fetch_and_clear_signet_section` +- [ ] `replace + with - in fetch_and_clear_signet_section` + +### line 224 +- [ ] `replace += with *= in fetch_and_clear_signet_section` + +### line 244 +- [ ] `replace extract_header_payload -> Option> with None` + +### line 264 +- [ ] `replace < with <= in read_script` + +### line 280 +- [ ] `replace < with <= in read_witness_stack` + +### line 294 +- [ ] `replace modified_merkle_root -> Result with Ok(Default::default())` + +### line 299 +- [ ] TIMEOUT - `replace > with < in modified_merkle_root` +- [ ] TIMEOUT - `replace > with == in modified_merkle_root` +- [ ] TIMEOUT - `replace > with >= in modified_merkle_root` + +### line 300 +- [ ] TIMEOUT - `replace == with != in modified_merkle_root` + +## silent_payments.rs (50) + +### line 46 +- [ ] `replace secp -> &'static Secp256k1 with Box::leak(Box::new(Secp256k1::new()))` +- [ ] `replace secp -> &'static Secp256k1 with Box::leak(Box::new(Secp256k1::from(Default::default())))` + +### line 145 +- [ ] TIMEOUT - `delete ! in backfill_sp_tweaks_cancellable` + +### line 180 +- [ ] TIMEOUT - `replace > with == in backfill_sp_tweaks_cancellable` + +### line 185 +- [ ] TIMEOUT - `replace <= with > in backfill_sp_tweaks_cancellable` + +### line 210 +- [ ] TIMEOUT - `replace >= with < in backfill_sp_tweaks_cancellable` + +### line 227 +- [ ] `replace < with <= in maybe_log_sptweaks_backfill` + +### line 233 +- [ ] `replace / with % in maybe_log_sptweaks_backfill` +- [ ] `replace / with * in maybe_log_sptweaks_backfill` + +### line 350 +- [ ] `replace < with <= in taproot_outs_from_records` +- [ ] `replace < with > in taproot_outs_from_records` + +### line 355 +- [ ] `replace < with <= in taproot_outs_from_records` + +### line 392 +- [ ] `replace < with == in build_tx_and_prevouts` +- [ ] `replace < with > in build_tx_and_prevouts` +- [ ] `replace < with <= in build_tx_and_prevouts` + +### line 404 +- [ ] `replace < with <= in build_tx_and_prevouts` + +### line 426 +- [ ] `replace input_hash_mul_a -> Option<[u8; 33]> with None` + +### line 429 +- [ ] `replace < with <= in input_hash_mul_a` + +### line 434 +- [ ] `replace + with - in input_hash_mul_a` + +### line 523 +- [ ] `replace && with || in is_p2wpkh` +- [ ] `replace && with || in is_p2wpkh` + +### line 528 +- [ ] `replace && with || in is_p2pkh` + +### line 529 +- [ ] `replace && with || in is_p2pkh` + +### line 530 +- [ ] `replace && with || in is_p2pkh` + +### line 531 +- [ ] `replace && with || in is_p2pkh` + +### line 532 +- [ ] `replace && with || in is_p2pkh` + +### line 536 +- [ ] `replace && with || in is_p2sh` +- [ ] `replace && with || in is_p2sh` +- [ ] `replace && with || in is_p2sh` +- [ ] `replace == with != in is_p2sh` + +### line 540 +- [ ] `replace < with == in witness_version` +- [ ] `replace || with && in witness_version` +- [ ] `replace < with <= in witness_version` +- [ ] `replace < with > in witness_version` +- [ ] `replace > with < in witness_version` +- [ ] `replace > with == in witness_version` +- [ ] `replace > with >= in witness_version` + +### line 544 +- [ ] `delete match arm 0x00 in witness_version` + +### line 545 +- [ ] `delete match arm v @0x51..= 0x60 in witness_version` +- [ ] `replace - with + in witness_version` +- [ ] `replace - with / in witness_version` + +### line 549 +- [ ] `replace || with && in witness_version` +- [ ] `delete ! in witness_version` +- [ ] `replace != with == in witness_version` + +### line 590 +- [ ] `replace < with <= in nums_h_script_path` + +### line 593 +- [ ] `replace - with + in nums_h_script_path` + +### line 594 +- [ ] `replace < with <= in nums_h_script_path` +- [ ] `replace < with > in nums_h_script_path` + +### line 667 +- [ ] `replace && with || in is_p2sh_p2wpkh_redeem` +- [ ] `replace && with || in is_p2sh_p2wpkh_redeem` diff --git a/docs/mutants/rbitcoin-primitives.md b/docs/mutants/rbitcoin-primitives.md new file mode 100644 index 000000000..9c255ec74 --- /dev/null +++ b/docs/mutants/rbitcoin-primitives.md @@ -0,0 +1,50 @@ +# rbitcoin-primitives Mutants - Full Specifics Index + +Generated from 16m run: 4 missed + 8 timeouts = 12 entries + +| File | Total | Missed | Timeout | +| :--- | ---: | ---: | ---: | +| `script_sigops.rs` | 6 | 2 | 4 | +| `hex.rs` | 2 | 0 | 2 | +| `lib.rs` | 2 | 2 | 0 | +| `scriptnum.rs` | 2 | 0 | 2 | + +## script_sigops.rs (6) + +### line 13 +- [ ] TIMEOUT - `replace += with *= in script_sigop_count` + +### line 14 +- [ ] TIMEOUT - `replace <= with > in script_sigop_count` + +### line 41 +- [ ] `replace > with < in script_sigop_count` +- [ ] `replace > with == in script_sigop_count` +- [ ] TIMEOUT - `replace > with >= in script_sigop_count` + +### line 44 +- [ ] TIMEOUT - `replace += with -= in script_sigop_count` + +## hex.rs (2) + +### line 97 +- [ ] TIMEOUT - `replace += with *= in decode` + +### line 103 +- [ ] TIMEOUT - `replace from_digit -> Result with Ok(0)` + +## lib.rs (2) + +### line 62 +- [ ] `replace > with >= in rbitcoin_subversion` + +### line 124 +- [ ] `replace schema_file_openable -> bool with true` + +## scriptnum.rs (2) + +### line 31 +- [ ] TIMEOUT - `replace > with >= in scriptnum_encode` + +### line 32 +- [ ] TIMEOUT - `replace & with | in scriptnum_encode` From 1cb3e6edc4afc97323db90c985ee7150d21dd182 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 16:20:23 -0400 Subject: [PATCH 10/12] docs(mutants): fix generated date to actual runs Sep 19 night -> Sep 20 16:14 ET, enforce lowercase --- docs/mutants/{MISSED.md => missed.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename docs/mutants/{MISSED.md => missed.md} (72%) diff --git a/docs/mutants/MISSED.md b/docs/mutants/missed.md similarity index 72% rename from docs/mutants/MISSED.md rename to docs/mutants/missed.md index 9be5066e0..f06fee421 100644 --- a/docs/mutants/MISSED.md +++ b/docs/mutants/missed.md @@ -1,6 +1,6 @@ # Mutants Baseline -> Generated: 2026-05-13 · Runner: M4 mini · consensus 9h (2518 tested) · primitives 16m (292 tested) +> Generated: 2026-09-20 16:14 ET · Runner: M4 mini · consensus 2026-09-19 night → 2026-09-20 morning (9h, 2518 tested) · primitives 2026-09-20 ~15:00 ET (16m, 292 tested) | Crate | Tested | Missed | Timeout | Details | | :--- | ---: | ---: | ---: | :--- | From eea18246988e2536456edc1341bf5a2ce0e61e54 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 17:15:30 -0400 Subject: [PATCH 11/12] ci: fix mutants weekly fail-fast false, move concurrency to pr job only --- .github/workflows/mutants.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index c4ff7db66..72a11131e 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -13,13 +13,12 @@ on: permissions: contents: read -concurrency: - group: mutants-${{ github.ref }} - cancel-in-progress: true - jobs: mutants-pr: if: github.event_name == 'pull_request' + concurrency: + group: mutants-pr-${{ github.ref }} + cancel-in-progress: true runs-on: ubuntu-latest timeout-minutes: 30 steps: @@ -41,6 +40,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 360 strategy: + fail-fast: false matrix: shard: [0, 1, 2, 3, 4, 5, 6, 7] steps: From 55a1caf738b2690c84b43d0513a837afc5493209 Mon Sep 17 00:00:00 2001 From: Hero-Gamer Date: Sun, 20 Sep 2026 17:26:07 -0400 Subject: [PATCH 12/12] fix: dedup .gitignore mutants.out --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 65e71c724..fd623fbb1 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,3 @@ signet*.log # cargo mutants output mutants.out/ -mutants.out/