Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .github/workflows/mutants.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Weekly cargo-mutants + PR in-diff advisory. Not a required PR check.
# Must pass --workspace: default-members is rbitcoin-node only.
# Owner: TESTING.md (Mutation testing). Snapshot lists: docs/mutants/.

name: mutants
on:
schedule:
Expand All @@ -22,13 +26,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: false
fetch-depth: 0
- uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b
- uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af
- 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
Expand All @@ -44,16 +48,16 @@ jobs:
matrix:
shard: [0, 1, 2, 3, 4, 5, 6, 7]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: false
- uses: dtolnay/rust-toolchain@a5f673d0ba8626c3977bb416a1612774bc82181b
- uses: taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af
- 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 --workspace --shard ${{ matrix.shard }}/8 -j 2
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: mutants-${{ matrix.shard }}
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ before 1.0).

### Changed

- **Weekly cargo-mutants:** `mutants.yml` — PR `--workspace --in-diff`
advisory (`continue-on-error`); Sunday 8-shard `--workspace` sweep.
Must use `--workspace` (`default-members` is node). Snapshot lists:
[`docs/mutants/`](docs/mutants/). How to run: [`TESTING.md`](TESTING.md).

- **Electrum/Esplora no longer require `--sh-index` to bind.** Address and
scripthash methods return `scripthash index disabled` (Electrum JSON-RPC
error; Esplora HTTP 503). Txid/outpoint/block/fees work. Channel watches
Expand Down
5 changes: 3 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ to us. `regtest_rpc.rs` / `regtest_pad.rs` stay in the denominator.
shipped path that drives the real entry point.
4. Re-run `./scripts/coverage.sh` until the ratio is **≥ 92%**.

## Structural lints, CRAP, Miri
## Structural lints, CRAP, Miri, mutants

These do **not** measure operator RSS ([`docs/ibd-memory.md`](./docs/ibd-memory.md)
owns caps). They catch the *shapes* of unbounded heap / leaked tasks, untested
Expand All @@ -250,9 +250,10 @@ matches scalar in default tests). Owner: [`docs/quality.md`](./docs/quality.md).
| **cargo-crap** | After LCOV, `./scripts/coverage.sh` calls `./scripts/coverage-crap.sh` (skip if `cargo-crap` missing). `--fail-above --threshold 30`; `.cargo-crap.toml` allowlists today's production CRAP>30 functions (remove a name when it scores ≤30). Dry-run: `CRAP_DRY_RUN=1 ./scripts/coverage-crap.sh`. Self-test: `./scripts/coverage-crap.test.sh` | Rides required `coverage`. No `--fail-regression` (llvm-cov coverage % jitters per function) |
| **coverage ignore / badge** | `./scripts/coverage.test.sh` (filename ignore, Tier A IBD not skipped, 92% floor, Shields JSON). Publish dry-run: `BADGE_DRY_RUN=1 ./scripts/publish-coverage-badge.sh` | `test` job self-test; `coverage` job writes `coverage/badge.json` and, on green `master`, pushes `badges/coverage.json` |
| **Miri** | `./scripts/miri.sh` → `cargo +nightly miri test -p rbitcoin-primitives`. Dry-run: `MIRI_DRY_RUN=1 ./scripts/miri.sh`. Self-test: `./scripts/miri.test.sh` | Nightly `miri.yml` (not required). Never `--workspace` |
| **cargo-mutants** | Must pass `--workspace` (`Cargo.toml` `default-members` is `rbitcoin-node` only; without `--workspace` the list is ~7 mutants). PR advisory: `git diff origin/<base>.. --unified=0 > git.diff` then `cargo mutants --workspace --in-diff git.diff -j 2`. Weekly: `cargo mutants --workspace --shard N/8 -j 2`. Snapshot of missed/timeouts: [`docs/mutants/`](docs/mutants/). | Weekly `mutants.yml` Sunday 03:00 UTC, 8 shards, 360min cap (not required). `workflow_dispatch`. PR job `mutants-pr` is `continue-on-error` (not a merge gate). First Sunday wall-clock is still a measurement. |

Artifact silos above are unchanged: ast-grep / Miri dry-run / crap dry-run do
not write `target/`.
not write `target/`. `mutants.out/` is gitignored.

### Mature-chain fixtures

Expand Down
22 changes: 6 additions & 16 deletions crates/rbitcoin-primitives/src/script_sigops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@ 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]
Expand Down Expand Up @@ -113,6 +97,12 @@ mod tests {
script_sigop_count(&[0x4e, 0x01, 0x00, 0x00, 0x00, 0xcd, 0xac], false),
1
);
assert_eq!(script_sigop_count(&[0x4c, 2, 0xac], true), 0);
assert_eq!(script_sigop_count(&[0x4c, 1, 0xac], true), 0);
assert_eq!(script_sigop_count(&[0x4d, 1, 0, 0xac], true), 0);
assert_eq!(script_sigop_count(&[0x02, 0x00], true), 0);
assert_eq!(script_sigop_count(&[0x4c, 2, 0xac, 0xac], true), 0);
assert_eq!(script_sigop_count(&[0x4c, 2, 0xac, 0xac, 0xac], true), 1);
}

#[cfg(miri)]
Expand Down
1 change: 1 addition & 0 deletions docs/ORIENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Before the first edit in a crate, read `crates/<name>/AGENTS.md` when that file
| Which head file (tx / header / scripthash) | [`heads.md`](./heads.md) |
| Crash, tip-as-commit, kill-9 | [`crash-recovery.md`](./crash-recovery.md) |
| Tests, budgets, coverage, fixtures | [`../TESTING.md`](../TESTING.md) |
| cargo-mutants (weekly sweep, PR advisory) | [`../TESTING.md`](../TESTING.md) (Mutation testing); snapshot [`mutants/`](./mutants/) |
| Multi-step plan (Red → Green → Refactor) | [`how-we-plan.md`](./how-we-plan.md) |
| cargo / clippy / deny / rustc logs (do not load into the session) | [`how-we-plan.md`](./how-we-plan.md) (Agent RAM) |
| `rearden-grok[bot]` operator VM (ignore unless that identity) | [`../rearden-vm-HOST.md`](../rearden-vm-HOST.md) |
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ into `AGENTS.md`.
| [`errata.md`](./errata.md) | Known one-off store/confirm quirks. |
| [`peer-clients.md`](./peer-clients.md) | Hornet Node and satd: what to steal (tests/ideas) and what not to copy. Ranked items stay here; do not copy into quality.md. |
| [`lightning.md`](./lightning.md) | CLN and LDK as Bitcoin backends: five `bcli` calls, Esplora/Electrum chain sync, `--sh-index` API matrix. Not LND. |
| [`mutants/`](./mutants/) | Generated cargo-mutants missed/timeout snapshot. How to run / CI: [`TESTING.md`](../TESTING.md). Not a quality backlog. |
| [`external_findings/`](./external_findings/) | Numbered audit reports + regression pointers. Do not flatten into CHANGELOG. |

## Root (stay at root)
Expand Down
14 changes: 11 additions & 3 deletions docs/mutants/missed.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# Mutants Baseline
# cargo-mutants snapshot

> 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)
How to run and what CI does: [`../../TESTING.md`](../../TESTING.md)
(Mutation testing). This directory is a **generated** missed/timeout list
from a host run, not the quality roadmap
([`../quality.md`](../quality.md)).

Generated: 2026-09-20 16:14 ET. Host: 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 |
| :--- | ---: | ---: | ---: | :--- |
| `rbitcoin-primitives` | 292 | 4 | 8 | [./rbitcoin-primitives.md](./rbitcoin-primitives.md) |
| `rbitcoin-consensus` | 2518 | 304 | 38 | [./rbitcoin-consensus.md](./rbitcoin-consensus.md) |

### Top files - consensus
### 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
4 changes: 3 additions & 1 deletion docs/mutants/rbitcoin-consensus.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# rbitcoin-consensus Mutants - Full Specifics Index
# rbitcoin-consensus mutants (generated)

Owner: [`../../TESTING.md`](../../TESTING.md). Index: [`missed.md`](./missed.md).

Generated from 9h run: 304 missed + 38 timeouts = 342 entries

Expand Down
4 changes: 3 additions & 1 deletion docs/mutants/rbitcoin-primitives.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# rbitcoin-primitives Mutants - Full Specifics Index
# rbitcoin-primitives mutants (generated)

Owner: [`../../TESTING.md`](../../TESTING.md). Index: [`missed.md`](./missed.md).

Generated from 16m run: 4 missed + 8 timeouts = 12 entries

Expand Down
3 changes: 2 additions & 1 deletion docs/quality.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ in [`CHANGELOG.md`](../CHANGELOG.md). 1.0 product gates:
**Last reaudit:** 2026-09-17. Schema **24**. Core functional **75**
`test_runner` jobs (**69** inventory `run`; Core expands transport twins and
`wallet_txn_*` flags) / **198** `skip`. Findings **001–023** fixed. Nightly
fuzz **20** jobs. Previous: 2026-09-15.
fuzz **20** jobs. Weekly mutants **8** shards (not required; owner
[`TESTING.md`](../TESTING.md)). Previous: 2026-09-15.

| Section | Purpose |
|---------|---------|
Expand Down
Loading