fuzz: Marinade crucible harness + FuzzCorp CI - #93
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Adds a coverage-guided fuzz harness for `marinade_finance` under fuzz/marinade, driven against a fork of real mainnet Marinade state, plus a GitHub Actions workflow that builds it and submits a bundle to FuzzCorp on every push to main. - fuzz/marinade/src/main.rs — the harness. Runtime invariants P-0001..P-0014 (conservation, solvency, supply integrity, no-free-value, and P-0007, a target-panic detector) are asserted after every action. - fuzz/marinade/fixtures/mainnet/** — real mainnet account snapshots, embedded at compile time (include_bytes!). - fuzz/marinade/programs/marinade_program.so — the target program, loaded at runtime. - fuzz/marinade/idls/marinade.json — program IDL, read at compile time by declare_fuzz_program!. - fuzz/marinade/build-bundle.sh — builds the harness and assembles a FuzzCorp bundle (amd64, crucible driver) under build/. - .github/workflows/fuzzcorp.yml — ubuntu-latest (amd64, native — matches the worker fleet) build + upload via asymmetric-research/fuzz-upload-action@v2. crucible deps are pinned to rev 432481a (immune to branch rebases). Three documented findings are suppressed in this campaign build so the P-0007 panic detector surfaces only NEW panics rather than re-reporting known ones. CI needs three repo settings: secret FUZZ_API_KEY, vars FUZZ_ORGANIZATION=marinade and FUZZ_PROJECT=liquid-staking-program. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove non-build fixture metadata (per-account *.json, *.txt address lists, extra *.md) — only the *.bin snapshots are embedded, so these just bloated the PR. 102 files removed. - Consolidate the README into one short file. - Cap fuzz target selection to a 5-validator/stake subset (SCOUT_FORK_FUZZ_N): the real fork loads ~692 validators / ~46 stakes, which spread the fuzzer thin; it now concentrates on 5 targets and drives them into deeper states. Only the target-selection picks are capped — validator lookups and merge-append keep the real counts, so the fork stays consistent (no invariant-consistency change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stop committing generated/bulky artifacts and fuzz each PR against its own program: - Remove the committed program .so (1.2M) and IDL (96K). CI now builds them from this repo's program source with the pinned anchor 0.27 / solana 1.14.29 toolchain (via the verifiable-build image), so every PR is fuzzed against its own program build rather than a stale snapshot. - Compress the 97 mainnet fixture .bin files into one 160K archive (fixtures-mainnet.tar.gz); build-bundle.sh unpacks it before the include_bytes! build. - Workflow now runs on every pull_request and on push to main (was push-only), and uploads only when secrets are available (fork PRs still build as a check). fuzz/marinade now tracks just the harness source, Cargo files, README, build script, and the fixtures archive.
|
Superseded by #96 — recreated with clean commit history (no AI attribution) and the program/IDL built in CI instead of committed. |
Track crucible `main` (branch, not a pinned rev) so the harness is built and fuzzed against the latest fuzzer. CI adds a `cargo update -p crucible-*` step before the build to pull the newest main on every run. Combined with building the program from source per-PR, nothing is a static snapshot: each change is compiled against the latest fuzzer and the freshly-built program, then fuzzed. Verified locally: harness builds + fuzzes clean against crucible main.
What
Adds a coverage-guided fuzz harness for
marinade_financeunderfuzz/marinade, plus a GitHub Actions workflow that builds and submits a bundle to FuzzCorp — building everything fresh on every PR, nothing static.The harness runs against a fork of real mainnet Marinade state and asserts runtime invariants after every action:
overflow-checks = true,unwrap/expect, index OOB,assert!) are swallowed by the VM as failed txs, so this scans tx logs and turns any target panic into a reported crash.CI — everything built from source, on every PR
.github/workflows/fuzzcorp.ymlruns on every PR and push to main (ubuntu-latest, amd64 — matches the FuzzCorp fleet):anchor buildwith the repo's pinned anchor 0.27 / solana 1.14.29 toolchain (via the verifiable-build image). So each change is fuzzed against its own program, not a committed.sosnapshot.main—cargo update -p crucible-*pulls the latest fuzzer before building the harness.asymmetric-research/fuzz-upload-action@v2.Required repo configuration (Settings → Secrets and variables → Actions):
FUZZ_API_KEY— a FuzzCorp service-account keyFUZZ_ORGANIZATION=marinadeFUZZ_PROJECT=liquid-staking-programNotes
.soand IDL are built in CI; the 97 mainnet fixture.binfiles are shipped as one 160Kfixtures-mainnet.tar.gz(embedded at compile time;build-bundle.shunpacks it).SCOUT_FORK_FUZZ_N) so it drives a few targets into deep states rather than spreading across ~692 validators.repro_findingsfeature re-enables all three for one-time verification.)