use crate::{
hardcoded_config_12, hardcoded_config_12_verifier, hardcoded_config_16,
hardcoded_config_16_verifier, hardcoded_config_20, hardcoded_config_20_verifier,
hardcoded_config_24, hardcoded_config_24_verifier, hardcoded_config_26,
hardcoded_config_26_verifier, hardcoded_config_28, hardcoded_config_28_verifier,
hardcoded_config_30, hardcoded_config_30_verifier, prover::prove_with_transcript,
transcript::FiatShamir, verifier::verify_with_transcript, FinalizedLigeritoProof,
};
use binary_fields::{BinaryElem128, BinaryElem32};
use std::marker::PhantomData;
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-parallel")]
pub use wasm_bindgen_rayon::init_thread_pool;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
macro_rules! console_log {
($($t:tt)*) => (log(&format!($($t)*)))
}
fn create_transcript(transcript_type: &str) -> Result<FiatShamir, JsValue> {
match transcript_type {
"sha256" => Ok(FiatShamir::new_sha256(0)),
#[cfg(feature = "transcript-merlin")]
"merlin" => Ok(FiatShamir::new_merlin()),
#[cfg(feature = "transcript-blake2b")]
"blake2b" => Ok(FiatShamir::new_blake2b()),
_ => Err(JsValue::from_str(&format!(
"Unsupported transcript: {}. Available: sha256{}{}",
transcript_type,
if cfg!(feature = "transcript-merlin") {
", merlin"
} else {
""
},
if cfg!(feature = "transcript-blake2b") {
", blake2b"
} else {
""
},
))),
}
}
#[wasm_bindgen]
pub fn prove(
polynomial: &[u32],
config_size: u8,
transcript: Option<String>,
) -> Result<Vec<u8>, JsValue> {
let transcript_type = transcript.as_deref().unwrap_or("sha256");
let fs = create_transcript(transcript_type)?;
let poly: Vec<BinaryElem32> = polynomial.iter().map(|&x| BinaryElem32::from(x)).collect();
macro_rules! prove_with_config {
($config_fn:ident, $expected_size:expr) => {{
let config = $config_fn(PhantomData::<BinaryElem32>, PhantomData::<BinaryElem128>);
if poly.len() != (1 << $expected_size) {
return Err(JsValue::from_str(&format!(
"Expected {} elements for config_size {}, got {}",
1 << $expected_size,
$expected_size,
poly.len()
)));
}
prove_with_transcript(&config, &poly, fs)
.map_err(|e| JsValue::from_str(&format!("Proving failed: {}", e)))?
}};
}
let proof = match config_size {
12 => prove_with_config!(hardcoded_config_12, 12),
16 => prove_with_config!(hardcoded_config_16, 16),
20 => prove_with_config!(hardcoded_config_20, 20),
24 => prove_with_config!(hardcoded_config_24, 24),
26 => prove_with_config!(hardcoded_config_26, 26),
28 => prove_with_config!(hardcoded_config_28, 28),
30 => prove_with_config!(hardcoded_config_30, 30),
_ => {
return Err(JsValue::from_str(&format!(
"Unsupported config_size: {}. Supported: 12, 16, 20, 24, 26, 28, 30",
config_size
)));
}
};
bincode::serialize(&proof)
.map_err(|e| JsValue::from_str(&format!("Serialization failed: {}", e)))
}
#[wasm_bindgen]
pub fn verify(
proof_bytes: &[u8],
config_size: u8,
transcript: Option<String>,
) -> Result<bool, JsValue> {
let transcript_type = transcript.as_deref().unwrap_or("sha256");
let fs = create_transcript(transcript_type)?;
let proof: FinalizedLigeritoProof<BinaryElem32, BinaryElem128> =
bincode::deserialize(proof_bytes)
.map_err(|e| JsValue::from_str(&format!("Deserialization failed: {}", e)))?;
macro_rules! verify_with_config {
($config_fn:ident) => {{
let config = $config_fn();
verify_with_transcript(&config, &proof, fs)
.map_err(|e| JsValue::from_str(&format!("Verification failed: {}", e)))?
}};
}
let result = match config_size {
12 => verify_with_config!(hardcoded_config_12_verifier),
16 => verify_with_config!(hardcoded_config_16_verifier),
20 => verify_with_config!(hardcoded_config_20_verifier),
24 => verify_with_config!(hardcoded_config_24_verifier),
26 => verify_with_config!(hardcoded_config_26_verifier),
28 => verify_with_config!(hardcoded_config_28_verifier),
30 => verify_with_config!(hardcoded_config_30_verifier),
_ => {
return Err(JsValue::from_str(&format!(
"Unsupported config_size: {}. Supported: 12, 16, 20, 24, 26, 28, 30",
config_size
)));
}
};
Ok(result)
}
#[wasm_bindgen]
pub fn get_polynomial_size(config_size: u8) -> Result<usize, JsValue> {
match config_size {
12 | 16 | 20 | 24 | 28 | 30 => Ok(1 << config_size),
_ => Err(JsValue::from_str(&format!(
"Unsupported config_size: {}",
config_size
))),
}
}
#[wasm_bindgen]
pub fn generate_and_prove(
config_size: u8,
seed: u64,
transcript: Option<String>,
) -> Result<Vec<u8>, JsValue> {
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
let transcript_type = transcript.as_deref().unwrap_or("sha256");
let fs = create_transcript(transcript_type)?;
let size: usize = 1 << config_size;
console_log!("Generating {} random elements in WASM...", size);
let mut rng = ChaCha8Rng::seed_from_u64(seed);
let poly: Vec<BinaryElem32> = (0..size)
.map(|_| BinaryElem32::from(rng.gen::<u32>()))
.collect();
console_log!("Polynomial generated, starting proof...");
macro_rules! prove_with_config {
($config_fn:ident) => {{
let config = $config_fn(PhantomData::<BinaryElem32>, PhantomData::<BinaryElem128>);
prove_with_transcript(&config, &poly, fs)
.map_err(|e| JsValue::from_str(&format!("Proving failed: {}", e)))?
}};
}
let proof = match config_size {
12 => prove_with_config!(hardcoded_config_12),
16 => prove_with_config!(hardcoded_config_16),
20 => prove_with_config!(hardcoded_config_20),
24 => prove_with_config!(hardcoded_config_24),
26 => prove_with_config!(hardcoded_config_26),
28 => prove_with_config!(hardcoded_config_28),
30 => prove_with_config!(hardcoded_config_30),
_ => {
return Err(JsValue::from_str(&format!(
"Unsupported config_size: {}. Supported: 12, 16, 20, 24, 26, 28, 30",
config_size
)));
}
};
console_log!("Proof generated, serializing...");
bincode::serialize(&proof)
.map_err(|e| JsValue::from_str(&format!("Serialization failed: {}", e)))
}
#[wasm_bindgen(start)]
pub fn init() {
console_error_panic_hook::set_once();
console_log!("Ligerito WASM module initialized");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_polynomial_size() {
assert_eq!(get_polynomial_size(12).unwrap(), 4096);
assert_eq!(get_polynomial_size(20).unwrap(), 1048576);
assert_eq!(get_polynomial_size(24).unwrap(), 16777216);
}
}