caliperforge/cf-invariants-jito
GitHub: caliperforge/cf-invariants-jito
一个针对 Jito tip-distribution 程序的 Anchor/Solana 不变性模糊测试 harness,运行于 Crucible 之上,通过 CI 验证四类不变性属性在干净实现与植入缺陷副本上的检测效果。
Stars: 0 | Forks: 0
# cf-invariants-jito
[](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, 区块链, 可视化界面, 智能合约, 测试框架, 通知系统