Loading...
Loading...
Compare original and translation side by side
#[kani::unwind]#[kani::solver]#[kani::unwind(N)]#[kani::solver(cadical)]// WRONG — helper checks more than the target property, adds loops
assert!(engine.check_all_invariants());
// RIGHT — asserts exactly what you're proving, no extra logic
assert!(engine.x.get() >= engine.y.get() + engine.z.get());kani::any()kani::assume()add_user()deposit()vaultlet mut engine = Engine::new(params)Box::new(Engine::new(params))max_accounts#[cfg(kani)]#[kani::unwind]#[kani::solver]#[kani::unwind(N)]#[kani::solver(cadical)]// 错误示例——辅助方法检查的内容超出目标属性,还会引入循环
assert!(engine.check_all_invariants());
// 正确示例——仅断言你要证明的内容,无额外逻辑
assert!(engine.x.get() >= engine.y.get() + engine.z.get());kani::assume()kani::any()add_user()deposit()vaultlet mut engine = Engine::new(params)Box::new(Engine::new(params))max_accounts#[cfg(kani)]cargo kani --harness proof_namecargo kani --harness proof_namekani::cover!(condition, "message")// VACUOUS — if operation always fails, nothing is checked
if result.is_ok() { assert!(invariant); }
// NON-VACUOUS — proof fails if operation can't succeed
match result {
Ok(_) => { /* assert properties */ },
Err(_) => { kani::assert(false, "must succeed"); unreachable!() }
};assume(false)kani::cover!()kani::assume()kani::cover!(condition, "message")// 空证明——如果操作始终失败,则不会检查任何内容
if result.is_ok() { assert!(invariant); }
// 非空证明——如果操作无法成功,证明会失败
match result {
Ok(_) => { /* 断言属性 */ },
Err(_) => { kani::assert(false, "must succeed"); unreachable!() }
};assume(false)kani::cover!()kani::assume()#[kani::unwind(N)]#[cfg(kani)]for i in 0..capacity#[cfg(kani)]#[kani::unwind(N)]#[cfg(kani)]for i in 0..capacity#[cfg(kani)]| Kani Output | Fix |
|---|---|
| Add |
| Timeout / solver hang | Add |
| Use |
| OOM / out of memory | Reduce state size, remove Box, fewer symbolic variables |
| Remove |
| Check |
| Kani输出 | 修复方案 |
|---|---|
| 添加 |
| 超时/求解器挂起 | 添加 |
| 使用 |
| 内存不足(OOM) | 减小状态大小,移除Box,减少符号变量 |
所有路径均触发 | 移除 |
| 检查 |
| Pattern | When to Use | What It Proves |
|---|---|---|
| Conservation | Moves, creates, or destroys quantities | Accounting equation preserved |
| Frame / Isolation | Targets one entity in multi-entity system | Bystander entities unchanged |
| INV Preservation | Any state mutation | Canonical invariant holds before and after |
| Error Path | Input validation / preconditions | Specific error + state completely unchanged |
| Monotonicity | Counters, timestamps, accumulators | Value only moves in one direction |
| Idempotency | Settlement, sync, recompute | Applying twice = applying once |
| Arithmetic Safety | Numeric computation | No overflow/underflow/div-by-zero |
| Access Control | Privileged operations | Unauthorized callers rejected |
| State Machine | Lifecycle transitions | Only valid transitions occur |
| Inductive Delta | Core accounting (strongest form) | Equation holds with raw primitives |
| Lifecycle / Sequence | Multi-step user flows | Properties hold through chained operations |
| 模式 | 使用场景 | 证明内容 |
|---|---|---|
| 守恒性 | 移动、创建或销毁数量 | 会计等式保持不变 |
| 框架/隔离性 | 多实体系统中的单个目标实体 | 无关实体未被修改 |
| 不变量保持 | 任何状态变更 | 标准不变量在变更前后均成立 |
| 错误路径 | 输入验证/前置条件 | 特定错误 + 状态完全未变更 |
| 单调性 | 计数器、时间戳、累加器 | 值仅向一个方向变化 |
| 幂等性 | 结算、同步、重新计算 | 执行两次等同于执行一次 |
| 算术安全性 | 数值计算 | 无溢出/下溢/除零错误 |
| 访问控制 | 特权操作 | 拒绝未授权调用者 |
| 状态机 | 生命周期转换 | 仅发生有效转换 |
| 归纳增量 | 核心会计(最强形式) | 等式基于原始原语成立 |
| 生命周期/序列 | 多步骤用户流程 | 属性在链式操作中始终成立 |
#[cfg(kani)]
mod kani_proofs {
use super::*;
#[kani::proof]
// NO #[kani::unwind] — only add after getting unwinding assertion error
// NO #[kani::solver] — only add after getting timeout
fn proof_name() {
// 1. Build state through public API (NOT field mutation)
// 2. Symbolic inputs: kani::any() with NO kani::assume() bounds
// 3. Call function, handle result explicitly (no if result.is_ok())
// 4. Assert ONLY the target property using raw field access
// (NOT check_conservation or other aggregate methods)
// 5. kani::cover!() for non-vacuity
}
}#[cfg(kani)]
mod kani_proofs {
use super::*;
#[kani::proof]
// 不要使用#[kani::unwind] — 仅在出现unwinding assertion错误后添加
// 不要使用#[kani::solver] — 仅在出现超时后添加
fn proof_name() {
// 1. 通过公开API构建状态(不要直接修改字段)
// 2. 符号输入:使用无kani::assume()限制的kani::any()
// 3. 调用函数,显式处理结果(不要用if result.is_ok())
// 4. 仅通过直接访问字段来断言目标属性
// (不要使用check_conservation或其他聚合方法)
// 5. 使用kani::cover!()确保非空性
}
}#[cfg(kani)] const MAX_ITEMS: usize = 4;[workspace.metadata.kani] flags = { tests = true }#[cfg(kani)] extern crate kani;#[cfg(kani)] const MAX_ITEMS: usize = 4;[workspace.metadata.kani] flags = { tests = true }#[cfg(kani)] extern crate kani;