Tutorial Verifikasi Rust Code dengan Kani Model Checker
AW
Axel W

Dipublikasikan 7 Juli 2026

Tutorial Verifikasi Rust Code dengan Kani Model Checker

Verifikasi formal adalah salah satu cara paling andal untuk memastikan code Rust Anda bebas dari bug memori, race condition, dan undefined behavior. Sayangnya, banyak developer menganggap verifikasi formal terlalu berat dan teoretis untuk dipakai di proyek nyata. Kani, sebuah model checker open source dari AWS, mengubah perspektif itu dengan memungkinkan verifikasi Rust code secara praktis melalui command line.

Berbeda dengan unit test yang hanya memeriksa input spesifik, Kani memverifikasi seluruh ruang kemungkinan input secara otomatis. Artinya, jika ada edge case yang menyebabkan panic, buffer overflow, atau assertion failure, Kani akan menemukannya dan memberikan concrete counterexample yang bisa langsung Anda debug. Tutorial ini akan membawa Anda dari instalasi hingga verifikasi pertama dengan Kani.

Apa Itu Kani dan Bagaimana Cara Kerjanya

Kani adalah model checker yang dibuat khusus untuk Rust. Ia bekerja dengan menerjemahkan Rust code menjadi representasi formal, lalu menggunakan backend C Bounded Model Checker (CBMC) untuk mengeksplorasi seluruh execution path dalam batas tertentu. Proses ini memastikan bahwa property yang Anda tentukan, seperti absence of panic atau correctness of invariant, berlaku untuk semua kemungkinan input.

Kani memanfaatkan attribute #[kani::proof] untuk menandai fungsi yang ingin diverifikasi. Fungsi ini disebut harness, mirip dengan test function tapi tanpa input manual. Kani secara otomatis menghasilkan nondeterministic values untuk parameter harness, lalu memeriksa apakah ada kombinasi input yang membuat harness gagal. Jika ditemukan, Kani melaporkan counterexample konkret yang memicu kegagalan.

Langkah 1: Instalasi Kani

Kani mensyaratkan Rust toolchain yang sudah terinstall. Pastikan Anda memiliki Rust versi terbaru via rustup. Setelah itu, instal Kani menggunakan installer resmi:

cargo install --locked kani-verifier
cargo kani setup

Perintah cargo kani setup akan mendownload CBMC binary dan dependencies lain yang dibutuhkan Kani. Proses ini biasanya memakan waktu beberapa menit tergantung koneksi internet. Setelah selesai, verifikasi instalasi dengan:

cargo kani --version

Langkah 2: Membuat Proyek Rust Pertama untuk Diverifikasi

Buat proyek Rust baru dan tambahkan dependency Kani. Untuk tutorial ini, kita akan memverifikasi fungsi sederhana yang melakukan operasi aritmatika dengan potensi overflow:

cargo new kani-demo
cd kani-demo

Edit file src/lib.rs dan tambahkan fungsi yang ingin diverifikasi beserta harness-nya:

pub fn add_without_overflow(a: u32, b: u32) -> u32 {
    a + b
}

#[cfg(kani)]
mod verification {
    use super::*;

    #[kani::proof]
    fn check_add_no_overflow() {
        let a: u32 = kani::any();
        let b: u32 = kani::any();
        let result = add_without_overflow(a, b);
        kani::assert(result >= a, "result should not be less than a");
    }
}

Fungsi kani::any() menghasilkan nilai nondeterministic, artinya Kani akan mencoba semua kemungkinan nilai u32 untuk a dan b. Ini memungkinkan Kani menemukan edge case yang mungkin terlewat oleh unit test konvensional.

Langkah 3: Menjalankan Verifikasi Pertama

Jalankan Kani menggunakan cargo subcommand:

cargo kani

Kani akan mengompilasi code dalam mode verification, lalu menjalankan model checker. Pada contoh di atas, Kani seharusnya menemukan bahwa a + b bisa overflow, sehingga assertion result >= a bisa gagal untuk input tertentu. Outputnya akan terlihat seperti ini:

VERIFICATION RESULT: FAILED
Counterexample: a = 2147483648, b = 2147483648

Counterexample ini memberikan input konkret yang membuat property Anda gagal, memudahkan proses debug. Anda bisa langsung mereproduksi bug dengan input tersebut di environment development.

Langkah 4: Memperbaiki Code dan Memverifikasi Ulang

Perbaiki fungsi untuk menangani overflow dengan checked arithmetic:

pub fn add_checked(a: u32, b: u32) -> Option<u32> {
    a.checked_add(b)
}

Lalu update harness untuk memverifikasi bahwa hasil Some(result) selalu memenuhi invariant:

#[kani::proof]
fn check_add_checked() {
    let a: u32 = kani::any();
    let b: u32 = kani::any();
    if let Some(result) = add_checked(a, b) {
        kani::assert(result >= a &amp;&amp; result >= b, "result should be gte both inputs");
    }
}

Jalankan cargo kani lagi. Kali ini verifikasi seharusnya berhasil karena checked_add menangani overflow dengan mengembalikan None alih-alih panic. Kani memverifikasi bahwa untuk semua input yang menghasilkan Some, invariant tetap terjaga.

Langkah 5: Integrasi ke CI dengan GitHub Actions

Agar verifikasi tidak terlupakan, integrasikan Kani ke CI pipeline. AWS menyediakan GitHub Action resmi untuk Kani. Tambahkan file .github/workflows/kani.yml:

name: Kani Verification
on: [push, pull_request]
jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Kani
        uses: model-checking/kani-github-action@v1
        with:
          args: '--output-format=terse'

Dengan setup ini, setiap pull request akan secara otomatis diverifikasi sebelum merge. Ini memberikan jaminan tambahan bahwa perubahan code tidak memperkenalkan regression dalam bentuk panic atau assertion failure. Untuk proyek safety-critical, verifikasi formal di CI bisa menjadi pengganti atau pelengkap code review yang sangat powerful.

Tips Optimasi dan Batasan Kani

Model checking secara teoritis bisa menjadi lambat untuk code dengan loop tak terbatas atau data structure besar. Kani menggunakan bound untuk membatasi jumlah iterasi loop yang dieksplorasi. Jika proof berjalan terlalu lama, pertimbangkan untuk menambahkan loop unwind bound:

cargo kani --unwind 5

Selain itu, Kani saat ini lebih optimal untuk verifikasi level function atau crate individual, bukan whole application sekaligus. Pilih fungsi-fungsi kritis yang paling rentan bug sebagai target harness pertama Anda.

Kesimpulan

Kani membawa verifikasi formal ke ranah praktis bagi developer Rust. Dengan sedikit tambahan attribute dan harness function, Anda bisa membuktikan keabsahan property kritis pada code tanpa menulis ratusan unit test. Integrasi ke CI memastikan bahwa bukti keabsahan tersebut tetap valid seiring evolusi codebase. Untuk tim yang serius soal reliability, Kani adalah investment yang worth dipertimbangkan.