caliperforge/cf-invariants-jito

GitHub: caliperforge/cf-invariants-jito

一个针对 Jito tip-distribution 程序的 Anchor/Solana 不变性模糊测试 harness,运行于 Crucible 之上,通过 CI 验证四类不变性属性在干净实现与植入缺陷副本上的检测效果。

Stars: 0 | Forks: 0

# cf-invariants-jito [![ci](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/2dc246bbbb230642.svg)](https://github.com/caliperforge/cf-invariants-jito/actions/workflows/ci.yml) **一个用于 [Jito tip-distribution program](https://github.com/jito-foundation/jito-programs/tree/master/mev-programs/programs/tip-distribution) 的 invariant-fuzzing harness,运行在 [Crucible](https://github.com/asymmetric-research/crucible) 上。** cf-invariants-jito 是一个专注的 harness,而不是一个新的 fuzzer。它将 上游的 Jito tip-distribution program 从 `anchor-lang` 0.31.1 迁移 到 `anchor-lang` 1.0.1,以便由 Crucible v0.2.0(LibAFL + LiteSVM)驱动,随后在一个干净的参考实现和四个植入 bug 的副本上运行四类 invariant。每次推送时,CI 都会重建全部五个 program 变体,并断言 `clean = 0` 个违规,以及每个类别中 `planted >= 1` 个违规。 这是以下项目的同级工件: [cf-invariants-anchor](https://github.com/caliperforge/cf-invariants-anchor) (通用的 Anchor / Crucible invariant 编写脚手架)以及 [cf-invariants](https://github.com/caliperforge/cf-invariants) (Cairo / Starknet / snforge),由同一运营方发布。 ## 范围 — Jito tip-distribution 是什么,此 harness 涵盖什么 Jito tip-distribution program 是 Solana 上 [Jito](https://www.jito.network/) MEV-redistribution 技术栈的链上部分。 当 Jito-Solana 验证者在一个 epoch 中赚取 MEV tip 后,该 program 将这些 tip 存放在一个 `TipDistributionAccount` (TDA) 中,一旦上传了基于每个申领人金额的 Merkle root,程序就会允许每个申领人带着 Merkle proof 调用 `claim` 以获取其份额。上游代码 位于 `jito-foundation/jito-programs/mev-programs/programs/tip-distribution` 并采用 Apache-2.0 许可证。 此 harness 不会修改生产环境的 program。它针对的是 该 program 的 **invariant 层面** —— 即无论 fuzz 了何种申领序列都必须成立的结构属性 —— 并 证明该 harness 既能在干净的参考实现上确认这些属性, 也能在每个类别中捕获到故意植入的回归。 ## 测试内容 — 四类 invariant 每个 invariant 都作为 Crucible fuzz fixture 针对 (a) 干净的 参考实现和 (b) 单一位置的植入 bug 副本运行。CI 断言 每个类别中 `clean = 0` 个违规和 `planted >= 1` 个违规。 | # | 类别 | 测试中的 invariant | 植入 bug 的位置 | |---|---|---|---| | 1 | `claim_amount_conservation` | `invariant_claim_amount_conservation` — 成功 `claim` 时从 TDA 扣除的总 lamports 等于贷记给申领人的 lamports。 | `programs/tip-distribution/src/state.rs::transfer_lamports` — debit 多减一的 off-by-one 错误。 | | 2 | `no_double_claim` | `invariant_no_double_claim` — 对于给定的 (TDA, 申领人) 配对,最多只能成功触发一次 `claim`。 | `programs/tip-distribution/src/lib.rs::claim` 运行时门控 — 接受重放。 | | 3 | `merkle_authority` | `invariant_merkle_proof_required` — 只有当提供的 proof 针对上传的 Merkle root 验证通过时,`claim` 才会成功。 | `programs/tip-distribution/src/merkle_proof.rs::verify` — 提前接受的短路逻辑。 | | 4 | `admin_gating` | `invariant_update_config_requires_authority` — 只有当前 config authority 签名时,`update_config` 才会成功。 | `programs/tip-distribution/src/lib.rs::update_config` — 丢弃了 authority 检查。 | 已发布 commit 上的 CI 结果:在所有四个类别中均为 `clean = 0` 且 `planted >= 1`。上方的 CI 徽章是事实来源 —— 如果它是红色的,说明 harness 已损坏。 ## 仓库结构 ``` . ├── programs/ # cf-invariants-jito port (anchor-lang 1.0.1) │ ├── tip-distribution/ # ported from jito-foundation/jito-programs │ └── vote-state/ # ported from jito-foundation/jito-programs ├── references/ │ ├── jito_tipdist_ref/ # clean baseline + 4 Crucible fuzz fixtures │ ├── jito_tipdist_ref_planted_claim_conservation/ # planted #1 │ ├── jito_tipdist_ref_planted_no_double_claim/ # planted #2 │ ├── jito_tipdist_ref_planted_merkle_authority/ # planted #3 │ └── jito_tipdist_ref_planted_admin_gating/ # planted #4 ├── .github/workflows/ci.yml # CI: workspace check + build-sbf + harness matrix ├── Cargo.toml # workspace ├── LICENSE # Apache-2.0 (CaliperForge) ├── NOTICE # Jito attribution + modification log └── README.md ``` 每个 invariant 的 fuzz-fixture 源码仅存放于 `references/jito_tipdist_ref/fuzz//src/main.rs` 下;CI 在运行前会将 相同的源码复制到每个植入 bug 的变体中,因此干净运行 与其植入 bug 运行之间的唯一区别在于加载到 LiteSVM 中的 `.so` 二进制文件。 ## 固定的工具链 这些是 CI 在每次推送时构建所用的版本(参见 [`.github/workflows/ci.yml`](./.github/workflows/ci.yml))。这些版本锁定是 根据每个上游的 `Cargo.toml` 经过经验证实的,而非目测: - Rust **stable**。 - `anchor-lang` **1.0.1** — 匹配 Crucible v0.2.0 的工作区。 - 上游 [Crucible](https://github.com/asymmetric-research/crucible) **v0.2.0** — 在 CI 中从源码构建 (`cargo install --path crates/crucible-fuzz-cli`)。 - 用于 `cargo-build-sbf` 的 Anza / Solana CLI **v2.1.21**。 - Solana platform-tools **v1.52**(作为 `--tools-version v1.52` 传入;Crucible v0.2.0 的依赖项需要 `edition2024` 支持,早期 platform-tools 的 rustc 无法构建)。 fuzz 的 `Cargo.toml` 通过位于 `../../../../../crucible/...` 的路径依赖引用 Crucible,即 `/../crucible`。CI 在 harness 步骤之前会将 Crucible v0.2.0 克隆到该同级路径下。 若要进行本地复现,请执行相同操作。 ## 从全新克隆复现 CI 在每次推送时都会精确执行以下步骤。本地复现是 可选的,并且要求已安装上述工具链并将其添加到 `PATH` 中。 ``` # 1. 克隆此 repo + Crucible v0.2.0 作为同级目录。 git clone https://github.com/caliperforge/cf-invariants-jito.git git clone --depth 1 --branch v0.2.0 \ https://github.com/asymmetric-research/crucible.git cd cf-invariants-jito # 2. Workspace 检查(也会在 CI 中作为 workspace-check job 运行)。 cargo check --workspace --locked # 3. 构建 cf-invariants-jito tip-distribution port (SBPF)。 cargo build-sbf --tools-version v1.52 \ --manifest-path programs/tip-distribution/Cargo.toml # 4. 构建 clean reference + 所有 4 个 planted twins。 for variant in jito_tipdist_ref \ jito_tipdist_ref_planted_claim_conservation \ jito_tipdist_ref_planted_no_double_claim \ jito_tipdist_ref_planted_merkle_authority \ jito_tipdist_ref_planted_admin_gating; do cargo build-sbf --tools-version v1.52 \ --manifest-path "references/${variant}/programs/tip-distribution/Cargo.toml" done # 5. 从源码构建 + 安装 Crucible CLI。 (cd ../crucible && cargo install --path crates/crucible-fuzz-cli --locked) # 6. 在一个 (class, variant) cell 上运行 harness —— 例如 claim-conservation clean。 # 预期:输出中没有 FUZZ_FINDING / INVARIANT VIOLATED 行。 (cd references/jito_tipdist_ref/fuzz/jito_claim_conservation && \ crucible run jito_tip_distribution invariant_claim_amount_conservation \ --release --timeout 30) # 7. 针对 planted twin 运行相同的 invariant。 # 预期:在约 30 秒内出现 FUZZ_FINDING / INVARIANT VIOLATED 行。 (cd references/jito_tipdist_ref_planted_claim_conservation/fuzz/jito_claim_conservation && \ crucible run jito_tip_distribution invariant_claim_amount_conservation \ --release --timeout 30) ``` CI 在每次推送时会对所有四个 invariant 运行第 2 至 7 步。 有关标准执行流程,请参见 [`.github/workflows/ci.yml`](./.github/workflows/ci.yml)。 ## 本项目不是什么 - **不是 Crucible 的分支。** Crucible 是 harness;cf-invariants-jito 是运行在其之上的 target + fuzz fixtures。LiteSVM 执行轨道 和基于 IDL 驱动的 fuzzing 管道归功于 Asymmetric Research。 - **不是 Jito 安全审计。** 每个植入的副本都是一个合成的 单站点回归,旨在证明对应的 invariant 类别会被触发。仅凭此 harness 无法对生产环境的 Jito program 的 安全性做出任何声明。 - **不是形式化验证工具。** 是随机 invariant fuzzing, 而非数学证明。 ## 报告问题,安全联系方式 在此 GitHub 仓库提 issue,或联系 [michael@caliperforge.com](mailto:michael@caliperforge.com)。 ## 许可证 Apache-2.0。请参见 [`LICENSE`](./LICENSE) 和 [`NOTICE`](./NOTICE)。 `NOTICE` 文件保留了 Jito 上游的 Apache-2.0 归属,并 描述了相对于上游的修改。 cf-invariants-jito 由 Michael Moffett 以 CaliperForge 的名义运营。CaliperForge 是一个个人独立运营的工程工作室。 此脚手架在 AI 辅助下构建。由 Michael Moffett(CaliperForge 运营者)编写和审查。完整政策请访问 [caliperforge.com/ai-disclosure](https://caliperforge.com/ai-disclosure)。 [caliperforge.com](https://caliperforge.com)
标签:Anchor, Solana, 区块链, 可视化界面, 智能合约, 测试框架, 通知系统