| Crates.io | sp1-ntt-gadget |
| lib.rs | sp1-ntt-gadget |
| version | 0.1.0 |
| created_at | 2025-12-08 05:58:11.106027+00 |
| updated_at | 2025-12-08 05:58:11.106027+00 |
| description | NTT/INTT Custom Gadget for Dilithium (ML-DSA-65) verification in SP1 zkVM with 60-bit soundness PIC |
| homepage | https://github.com/kota1026/pq-wallet-sp1-ntt-gadget- |
| repository | https://github.com/kota1026/pq-wallet-sp1-ntt-gadget- |
| max_upload_size | |
| id | 1972779 |
| size | 261,789 |
High-performance NTT/INTT implementation for Dilithium (ML-DSA-65) verification in SP1 zkVM with 60-bit soundness.
Add to your Cargo.toml:
[dependencies]
sp1-ntt-gadget = "0.1"
use sp1_ntt_gadget::{ntt::forward::ntt, ntt::inverse::intt, params::N};
fn main() {
// 256 coefficients in Z_q (q = 8,380,417)
let mut coeffs = [0u32; N];
coeffs[0] = 42;
coeffs[1] = 59;
// Forward NTT
let original = coeffs;
ntt(&mut coeffs);
// Inverse NTT (roundtrip)
intt(&mut coeffs);
assert_eq!(coeffs, original);
}
use sp1_ntt_gadget::{
ntt::forward::ntt,
pic::verifier::verify_ntt_simple,
params::N,
};
fn main() {
let mut coeffs = [0u32; N];
for i in 0..N {
coeffs[i] = (i as u32 * 12345) % 8_380_417;
}
let original = coeffs;
ntt(&mut coeffs);
// Verify NTT correctness (60-bit soundness)
let context = b"my-application-context";
assert!(verify_ntt_simple(&original, &coeffs, context).is_ok());
}
use sp1_ntt_gadget::precompile::sp1_hook::{
NttInput, execute_ntt_with_verification
};
fn main() {
let input = NttInput {
coefficients: [42u32; 256],
context: *b"sp1-ntt-gadget-context-v1\0\0\0\0\0\0\0",
};
let output = execute_ntt_with_verification(&input);
assert!(output.verified);
println!("NTT output: {:?}", &output.ntt_coefficients[..4]);
}
| Parameter | Value | Description |
|---|---|---|
| Q | 8,380,417 | Dilithium prime (q ≡ 1 mod 512) |
| N | 256 | Polynomial degree |
| NUM_CHALLENGES | 4 | PIC challenges (60-bit soundness) |
| Module | Description |
|---|---|
ntt::forward |
Forward NTT (Cooley-Tukey) |
ntt::inverse |
Inverse NTT (Gentleman-Sande) |
ntt::montgomery |
Montgomery arithmetic |
pic::challenge |
Fiat-Shamir challenge derivation |
pic::verifier |
NTT verification with PIC |
validation::input |
Coefficient range validation |
precompile::sp1_hook |
SP1 syscall integration |
| Operation | Time |
|---|---|
| NTT (forward) | ~1.3 µs |
| INTT (inverse) | ~1.9 µs |
| Verified NTT | ~5.1 µs |
| Metric | Value |
|---|---|
| Proof Size | 260 bytes |
| Proof Time | ~22 seconds |
| On-chain Verifiable | ✅ Yes |
# Run all tests (104 tests)
cargo test
# Run with specific test suite
cargo test --test ntt_gate1 # Gate 1: NTT correctness
cargo test --test pic_gate2 # Gate 2: PIC soundness
cargo test --test fuzz_ntt # Fuzzing (100k+ iterations)
MIT License - see LICENSE-MIT for details.
Contributions welcome! Please open an issue or PR.
Part of the PQ Wallet project - Post-Quantum Cryptography for Web3