Merancang Zero-Knowledge Virtual Machine (ZkVM) melibatkan kompromi fundamental antara soundness matematika dan efisiensi komputasi prover. Setiap batasan aljabar (polynomial constraint) yang ditambahkan ke sistem execution trace menjamin integritas eksekusi, tetapi secara langsung meningkatkan overhead pembuktian, memori GPU, dan kompleksitas verifikasi.
Arsitektur Monolithic Circuit vs Modular Chip (AIR)
Generasi awal ZkVM cenderung mengadopsi pendekatan sirkuit monolitik. Dalam model ini, satu tabel eksekusi besar menangani seluruh instruction set architecture (ISA), seperti RISC-V. Setiap baris sirkuit memuat kolom untuk semua register, ALU flag, memori, dan branching logic.
Kelemahan monolitik terletak pada inefisiensi ruang trace. Instruksi sederhana seperti ADD tetap mengalokasikan ruang kolom untuk operasi kompleks seperti perkalian 64-bit atau hashing. Akibatnya, derajat polinomial membengkak dan prover membuang siklus komputasi pada kolom kosong (padding).
Arsitektur modern seperti yang diadopsi OpenVM beralih ke pendekatan modular chip berbasis Algebraic Intermediate Representation (AIR). Eksekusi dipecah menjadi beberapa sub-tabel independen (sub-circuits atau "chips"):
- Core Chip: Menangani alur program counter (PC) dan decoding instruksi dasar.
- Memory Chip: Menggunakan permutation argument (seperti offline memory checking) untuk memvalidasi konsistensi read/write.
- Specialized Coprocessors: Menangani instruksi berat seperti
MUL,DIV, atau kriptografi (Keccak, SHA256) pada tabel terpisah dengan tinggi (height) dinamis.
Interkoneksi antar-chip dihubungkan menggunakan cross-table lookup arguments (misalnya LogUp). Pendekatan ini meminimalkan ukuran trace keseluruhan karena chip perkalian hanya diisi sebanyak instruksi perkalian dieksekusi.
Pelajaran Audit OpenVM: Risiko Under-constrained dan Soundness Bug
Modularitas meningkatkan fleksibilitas rekayasa software, namun memperkenalkan celah keamanan kritis pada batas antar-chip. Audit keamanan pada sistem seperti OpenVM sering mengungkap missing constraints atau under-constrained AIR.
Masalah paling umum terjadi ketika compiler atau prover witness generator menghitung nilai privat secara benar, tetapi constraint polinomial gagal membatasi nilai tersebut secara kaku. Akibatnya, penyerang dapat menyuntikkan witness palsu yang lolos evaluasi derajat polinomial.
Contoh Pola Celah: Range Check yang Hilang
Pada dekomposisi integer 32-bit ke dalam 4 byte, jika constraint polinomial hanya memeriksa penjumlahan tanpa membatasi rentang setiap byte ke [0, 255], soundness sirkuit runtuh:
// CONTOH UNDER-CONSTRAINED:
// Memeriksa: a0 + a1*256 + a2*65536 + a3*16777216 == val
// Masalah: a0, a1, a2, a3 tidak dibatasi ke range [0, 255].
// Prover manipulatif bisa memilih a0 > p (modulus) tanpa memicu error.
fn verify_decode_broken(builder: &mut AirBuilder, val: Expr, bytes: [Expr; 4]) {
let base = Expr::from(256);
let reconstructed = bytes[0]
+ bytes[1] * base
+ bytes[2] * base * base
+ bytes[3] * base * base * base;
builder.assert_zero(reconstructed - val);
// BUG: Missing range check untuk bytes[0..4]
}Dampak Finansial: Biaya Prover vs Kompleksitas Verifikasi
Optimasi sirkuit selalu berdampak pada arsitektur infrastruktur prover. Tiga faktor utama penentu biaya komputasi GPU/cloud meliputi:
- Trace Height & Degree: Komitmen polinomial (seperti FRI atau KZG) bergantung pada Number Theoretic Transform (NTT) dan Multi-Scalar Multiplication (MSM). Menurunkan derajat constraint dari 3 ke 2 secara signifikan memangkas waktu NTT pada GPU VRAM.
- Lookup Argument Overhead: Penggunaan LogUp yang berlebihan antar-chip modular membutuhkan inverse computation di finite field. Komputasi inversi field modular mahal jika tidak dibatch dengan Montgomery batch inversion.
- Verifikasi On-chain: Mengirim ribuan constraint langsung ke smart contract verifier (misalnya di Ethereum L1) tidak feasible secara biaya gas. Sistem ZkVM mengatasi ini dengan rekursi (recursive verification): proof AIR modular diringkas oleh sirkuit wrapper STARK-to-SNARK sebelum disubmit ke blockchain.
Pola Mitigasi: Strict Constraints Tanpa Membengkakkan Prover
Untuk menutup soundness bug tanpa menaikkan biaya prover, implementasikan pemisahan antara interaksi bus dan preprocessed tables. Gunakan preprocessed table global berukuran $2^{8}$ atau $2^{16}$ untuk memvalidasi range check via LogUp, daripada menulis constraint degree tinggi langsung di execution trace chip utama.
// POLA MITIGASI EFISIEN:
// Menggunakan Lookup Table global untuk enforce range check byte [0, 255]
fn verify_decode_sound(
builder: &mut AirBuilder,
val: Expr,
bytes: [Expr; 4],
byte_lookup_bus: &LookupBus
) {
let base = Expr::from(256);
let reconstructed = bytes[0]
+ bytes[1] * base
+ bytes[2] * base * base
+ bytes[3] * base * base * base;
// 1. Validasi dekomposisi nilai
builder.assert_zero(reconstructed - val);
// 2. Hubungkan ke lookup bus (biaya murah, tidak menaikkan degree polinomial chip)
for b in bytes.iter() {
byte_lookup_bus.send(builder, *b);
}
}Mitigasi ini menjaga derajat constraint lokal tetap bernilai 1 atau 2, mengalihkan beban verifikasi integritas data ke mekanisme lookup logaritmik yang dapat diproses secara paralel pada akselerator hardware.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!