# Kani Formal Verification for Synor This directory contains Kani model checking proofs for critical Synor components. ## What is Kani? Kani is a bit-precise model checker for Rust. It can verify that Rust programs are free of: - Runtime panics - Memory safety issues - Assertion violations - Undefined behavior Unlike property testing (proptest), Kani exhaustively checks **all possible inputs** within defined bounds. ## Installation ```bash # Install Kani cargo install --locked kani-verifier kani setup ``` ## Running Proofs ```bash # Run all Kani proofs in a crate cd crates/synor-consensus kani --tests # Run specific proof kani --harness utxo_add_never_overflows # Run with bounded loops (for performance) kani --harness utxo_conservation --default-unwind 10 ``` ## Proof Structure Each proof harness: 1. Uses `kani::any()` to generate arbitrary inputs 2. Sets up preconditions with `kani::assume()` 3. Executes the code under test 4. Asserts postconditions with `kani::assert()` or standard `assert!` ## Proofs Included ### UTXO Module (`crates/synor-consensus/src/utxo_kani.rs`) - `utxo_add_never_overflows` - Adding UTXOs cannot overflow total value - `utxo_conservation` - Total value is conserved across operations - `utxo_no_double_spend` - Same outpoint cannot exist twice ### Difficulty Module (`crates/synor-consensus/src/difficulty_kani.rs`) - `difficulty_bits_roundtrip` - bits conversion is approximately reversible - `difficulty_bounded_adjustment` - adjustment stays within bounds - `target_difficulty_inverse` - higher difficulty = smaller target ### Amount Module (`crates/synor-types/src/amount_kani.rs`) - `amount_checked_add_sound` - checked_add returns None on overflow - `amount_saturating_sub_bounded` - saturating_sub never exceeds original - `amount_max_supply_respected` - operations respect MAX_SUPPLY ## CI Integration Add to `.github/workflows/kani.yml`: ```yaml name: Kani Verification on: [push, pull_request] jobs: kani: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: model-checking/kani-github-action@v1 - run: kani --tests --workspace ``` ## Writing New Proofs ```rust #[cfg(kani)] mod kani_proofs { use super::*; #[kani::proof] fn my_function_never_panics() { let input: u64 = kani::any(); // Preconditions kani::assume(input < MAX_VALUE); // Code under test let result = my_function(input); // Postconditions assert!(result.is_ok()); } } ``` ## Limitations - Kani has bounded model checking, so loops need unwinding limits - Complex floating point is approximated - External FFI calls are stubbed - Network/filesystem operations are not verified ## References - [Kani Documentation](https://model-checking.github.io/kani/) - [AWS Kani Blog](https://aws.amazon.com/blogs/opensource/how-we-use-kani/) - [Kani GitHub](https://github.com/model-checking/kani)