caliperforge/cf-invariants-anchor
GitHub: caliperforge/cf-invariants-anchor
cf-invariants-anchor:基于AI的Solana智能合约属性生成与验证工具
Stars: 1 | Forks: 0
# cf-invariants-anchor
[](https://github.com/caliperforge/cf-invariants-anchor/actions/workflows/ci.yml)
**Solana / Anchor 上 [Crucible](https://github.com/asymmetric-research/crucible) 和 [Trident](https://github.com/Ackee-Blockchain/trident) 的 AI 不变量编写工具。**
cf-invariants-anchor 是两个用于 Solana 程序的开源不变量模糊测试
harness 的*附属工具*:
- **Crucible** (Asymmetric Research, MIT, LibAFL + LiteSVM, v0.2.0) — 主要的生成目标。
- **Trident** (Ackee Blockchain, MIT) — 次要的生成目标(在 Phase 1 阶段推出)。
我们**不会重构 harness**。Crucible 和 Trident 已经拥有了
LiteSVM 执行轨道以及基于 IDL 驱动的程序模糊测试
底层架构。尚未被覆盖的领域——也是本 crate 唯一
提供的功能——是位于它们之上的 **AI 建议不变量编写工具**:
接收一个 Anchor IDL,从类库中提出排序后的候选不变量(Phase 0 包含余额守恒;路线图中包含单调性、
访问控制、预言机时效性),并生成一个
可直接运行的包含 `#[fuzz_fixture]` + `#[invariant_test]` 的
源代码文件,供 Crucible 使用。
本包是针对 Cairo 的 [cf-invariants](../cf-invariants/) (Starknet / snforge) 的 Anchor 配套版本,由
同一运营商发布。
## 状态
**Phase 0 — 可用工件,1.0 之前版本。**
本构建中已上线的功能:
- `cf-invariants-anchor ingest ` — 将 Anchor 0.30 / Codama 风格的
IDL JSON 解析为类型化的合约接口(程序 id、指令、
每个存储账户的标量余额字段)。
- `cf-invariants-anchor suggest ` — 通过启发式建议器生成排序后的
候选不变量列表。**目前已提供三个类别**:`balance_conservation`、`monotonic_accounting`、
`access_control`。`InvariantClass` trait + `ClassRegistry` 使得
添加第四个(预言机/时效性)只需修改一个文件即可。
- `cf-invariants-anchor suggest --ai` — 通过
`cf-invariants-anchor-ai` 路由以获取 AI 建议的候选项。每个返回的
候选项都带有 `InvariantSource::AiSuggested { model,
prompt_version, timestamp_utc }`;一条 JSON 审计日志条目会被写入
`.cf-invariants-anchor/ai-log/.json`(包含 token 计数、
美元成本、响应的 SHA-256)。默认传输方式为 `MockTransport`
(确定性、无需 API key、CI 安全);当 CLI 使用 `--features live-ai` 构建且设置了
`CF_INVARIANTS_ANCHOR_AI_LIVE=1` 和
`ANTHROPIC_API_KEY` 时,将激活 `LiveAnthropicTransport`。
- `cf-invariants-anchor emit --target crucible` — 为选定的候选项渲染
兼容 Crucible 的模糊测试 fixture。每个
类别都有其自己的生成形态:余额使用 fixture 端账本 +
`fuzz_assert_eq!`;单调性使用 `last_seen_*` 快照 + `fuzz_assert_le!`;
访问控制使用攻击者密钥对探测 + 粘滞标志断言。
- `--target trident` — Phase-1 存根。生成操作会返回一个解释性的
占位符,以便在尚未接入 Trident
渲染的情况下仍能访问 CLI 接口。
- **三对参考合约**,每个发布的类别一对:
- `references/vault_ref{,_planted}` — `balance_conservation`。植入漏洞的提款操作转移了 `amount` lamports,但将
`vault.amount` 减去了 `amount-1`;守恒不变量能在 1 次提款中捕捉到
这种偏差。
- `references/counter_ref{,_planted}` — `monotonic_accounting`。添加了一个
`lifetime_deposited: u64` 棘轮字段;植入漏洞的提款操作在每次调用时都会递减它,导致终身计数器倒退。
- `references/admin_ref{,_planted}` — `access_control`。无漏洞的
提款操作强制要求 `seeds = [b"vault", depositor.key().as_ref()]`
且 `has_one = depositor`;植入漏洞的变体删除了这两个限制,因此任何
签名者都可以抽干任何 vault PDA。生成的攻击者探测
fixture 会在第一次成功的未授权提款时触发异常。
- **记分卡渲染器**,每当 `ai_suggestions_included > 0` 时,就会输出
AI 披露横幅。默认的参考运行
使用启发式来源,因此这些
记分卡上的横幅处于休眠状态(渲染器路径已通过测试覆盖);
`--ai` 标志会触发该横幅。
- 工作区测试套件(36 个测试,`cargo test --workspace`)。
## 它不包含什么
- **不是 Crucible 或 Trident 的分支。**两者均作为上游
依赖项提供;cf-invariants-anchor 仅负责编写不变量。
- **不是形式化验证工具。**属于随机化不变量搜索,
而非数学证明。
- **不能替代手动编写的不变量。**AI / 启发式
候选项始终被标记为 `UNVERIFIED`,直到合约
作者接受它们。
## 架构
`cf-invariants-anchor` 是一个包含五个 Rust crate 的 Cargo 工作区:
```
crates/
cf-invariants-anchor-cli/ # binary
cf-invariants-anchor-core/ # shared types: ContractSurface, InvariantCandidate, Scorecard
cf-invariants-anchor-idl/ # Anchor IDL parser → ContractSurface
cf-invariants-anchor-suggest/ # ClassRegistry + balance_conservation suggester
cf-invariants-anchor-emit/ # Render to Crucible / Trident-stub source
cf-invariants-anchor-report/ # Scorecard markdown + JSON renderer
references/
vault_ref{,_planted}/ # balance_conservation pair
counter_ref{,_planted}/ # monotonic_accounting pair
admin_ref{,_planted}/ # access_control pair
findings/
vault_ref_{clean,planted}/ # scorecard.expected.md + CI capture
counter_ref_{clean,planted}/ # scorecard.expected.md + CI capture
admin_ref_{clean,planted}/ # scorecard.expected.md + CI capture
docs/
architecture.md # design, emit-target abstraction, Crucible API record
ai-disclosure.md # AI involvement, disclosure path, audit log
scripts/
run_phase0_harness.sh # reproduce-from-clone driver
prompts/
invariant_suggestion_v1.txt # versioned prompt (Phase 1 AI path)
```
## 固定工具链
这些是 CI 在每次推送时构建所依据的版本(参见
[`.github/workflows/ci.yml`](./.github/workflows/ci.yml))。所有版本
锁定均已根据上游 tag 的 `Cargo.toml` 进行了经验性验证,
而非仅从代码结构粗略估计:
- Rust **stable** (工作区 MSRV: `1.79`)。
- `anchor-lang` **1.0.1** — 与 Crucible v0.2.0 的工作区匹配
(`asymmetric-research/crucible @ v0.2.0` 锁定了 `anchor-lang = "1.0.1"`)。
- Anza / Solana CLI **v2.1.21**,用于 `cargo-build-sbf`。
- Solana platform-tools **v1.52**(Crucible v0.2.0 的依赖项需要
edition2024 支持;早期的 platform-tools 附带 rustc 1.84,无法
构建它们 — 通过 `--tools-version v1.52` 传递)。
- 上游 Crucible **v0.2.0** 在 CI 中通过源码构建
(`cargo install --path crates/crucible-fuzz-cli`)。
模糊测试的 `Cargo.toml` 通过路径依赖引用 Crucible,位于
`../../../../../crucible/crates/crucible-fuzzer` — CI 将 Crucible 克隆到
`/../crucible`,因此该路径能够正确解析。如需在本地
重现,要么将 Crucible 克隆到该路径,要么本地化引入这两个 crate 并编辑
模糊测试的 Cargo.tomls。
参见 [`.tool-versions`](./.tool-versions)(仅供参考;以 CI 为准)。
## 安装
```
cargo install --path crates/cf-invariants-anchor-cli
```
## 快速开始
```
# Ingest 一个 Anchor IDL。
cf-invariants-anchor ingest references/vault_ref/idls/vault_ref.json
# 向 suggester 请求排序后的候选 invariant。
cf-invariants-anchor suggest references/vault_ref/idls/vault_ref.json
# 生成一个 Crucible #[fuzz_fixture] + #[invariant_test] 文件。
cf-invariants-anchor emit references/vault_ref/idls/vault_ref.json \
--target crucible \
--out references/vault_ref/fuzz/vault_ref/src/main.rs
```
## 端到端 Phase 0 演示
CI 每次推送时都会准确运行此流程;本地重现是可选的。参见
[`scripts/run_phase0_harness.sh`](./scripts/run_phase0_harness.sh) 获取
规范的驱动程序。
```
# 1. 构建干净的参考程序及其植入 twin (SBPF)。
cargo build-sbf --tools-version v1.52 \
--manifest-path references/vault_ref/programs/vault_ref/Cargo.toml
cargo build-sbf --tools-version v1.52 \
--manifest-path references/vault_ref_planted/programs/vault_ref/Cargo.toml
# 2. 生成 conservation invariant(已在此 repo 中预先生成)。
cf-invariants-anchor emit references/vault_ref/idls/vault_ref.json \
--target crucible \
--out references/vault_ref/fuzz/vault_ref/src/main.rs
cp references/vault_ref/fuzz/vault_ref/src/main.rs \
references/vault_ref_planted/fuzz/vault_ref/src/main.rs
# 3. 针对两个 variants 运行 Crucible(timeout 足够小以适用于 CI;
# 植入 bug 的最小 counterexample 为 2 个 action 并且会快速触发)。
(cd references/vault_ref/fuzz/vault_ref && \
crucible run vault_ref invariant_amount_conservation --release --timeout 30)
(cd references/vault_ref_planted/fuzz/vault_ref && \
crucible run vault_ref invariant_amount_conservation --release --timeout 30)
```
CI 工作流将这些运行的真实输出捕获到
`findings/vault_ref_{clean,planted}/scorecard.md` 中,并将其作为
`crucible-scorecards` 构建产物上传。同级的 `scorecard.expected.{json,md}`
文件作为编写的参考保留,以便进行差异对比。
## 路线图
| 阶段 | 范围 |
|-------|---------|
| **0** | IDL 接收 → 排序后的余额守恒候选 → Crucible 生成 → 记分卡渲染器。仅包含启发式建议器。✅ 已发布。 |
| **1** | AI 建议的不变量上线(Anthropic Claude Sonnet 路径:默认为 MockTransport,在 `--features live-ai` + 环境变量后启用 LiveAnthropicTransport)。单调性 + 访问控制类别已添加到建议器 + 生成器中。✅ 已发布。 |
| **2 (当前构建)** | `counter_ref`(单调性)+ `admin_ref`(访问控制)参考对,包含 CI Crucible 证明 — 每个新类别都能在 `clean=0 / planted≥1` 下捕获其植入的漏洞。✅ 已入库;下次推送时基于 CI 绿色状态进行门控。 |
| 3 | Trident 生成目标。预言机时效性类别。CI 记分卡偏差预警。缩减。多账户状态范围(使用完整的账户可变性集合分析代替名称启发式)。 |
## 报告问题与安全联系
在 GitHub 仓库中提交 issue,或联系
[team@caliperforge.com](mailto:team@caliperforge.com)。
对于涉及 cf-invariants-anchor 本身的敏感安全披露,
请直接联系 [michael@caliperforge.com](mailto:michael@caliperforge.com)。
## 许可证
Apache-2.0。参见 `LICENSE`。
cf-invariants-anchor 由 Michael Moffett 以 CaliperForge 的名义运营。CaliperForge 是一家个人运营的工程工作室。
在 AI 辅助下构建。由 CaliperForge 的运营者 Michael Moffett 编写和审查。完整政策请访问 [caliperforge.com/ai-disclosure](https://caliperforge.com/ai-disclosure)。关于 AI 模块的功能、审计日志路径以及如何禁用它的仓库内详细信息,请参见 [`docs/ai-disclosure.md`](./docs/ai-disclosure.md)。
[caliperforge.com](https://caliperforge.com)
标签:通知系统