#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::all, unused_imports)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc as alloc_crate;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, string::String, vec::Vec};
extern crate ligerito_binary_fields as binary_fields;
extern crate ligerito_merkle as merkle_tree;
#[cfg(feature = "prover")]
extern crate ligerito_reed_solomon as reed_solomon;
#[cfg(feature = "std")]
pub mod autosizer;
pub mod configs;
pub mod data_structures;
pub mod eval_proof;
pub mod sumcheck_polys;
pub mod sumcheck_verifier;
pub mod transcript;
pub mod utils;
pub mod verifier;
#[cfg(feature = "prover")]
pub mod ligero;
#[cfg(feature = "prover")]
pub mod prover;
#[cfg(feature = "prover")]
pub mod backend;
#[cfg(feature = "wasm")]
pub mod wasm;
#[cfg(feature = "wasm-raw")]
pub mod wasm_raw;
#[cfg(feature = "webgpu")]
pub mod gpu;
#[cfg(feature = "core_affinity")]
pub mod cpu_affinity;
pub use data_structures::{FinalizedLigeritoProof, VerifierConfig};
#[cfg(feature = "prover")]
pub use data_structures::ProverConfig;
pub use configs::{
hardcoded_config_12_verifier, hardcoded_config_16_verifier, hardcoded_config_20_verifier,
hardcoded_config_24_verifier, hardcoded_config_26_verifier, hardcoded_config_28_verifier,
hardcoded_config_30_verifier,
};
#[cfg(feature = "prover")]
pub use configs::{
hardcoded_config_12, hardcoded_config_16, hardcoded_config_20, hardcoded_config_24,
hardcoded_config_26, hardcoded_config_28, hardcoded_config_30,
};
#[cfg(feature = "std")]
pub use autosizer::{
config_info, config_info_for_log_size, verifier_config_for_log_size, verifier_config_for_size,
ConfigInfo, MAX_LOG_SIZE, MIN_LOG_SIZE,
};
#[cfg(all(feature = "std", feature = "prover"))]
pub use autosizer::{prover_config_for_log_size, prover_config_for_size};
pub use data_structures::*;
#[cfg(feature = "prover")]
pub use prover::{prove, prove_sha256, prove_with_evaluations, prove_with_transcript};
pub use sumcheck_verifier::SumcheckError;
pub use transcript::{FiatShamir, Sha256Transcript, Transcript, TranscriptType};
pub use verifier::{
verify, verify_complete, verify_complete_sha256, verify_debug, verify_sha256,
verify_with_evaluations, verify_with_transcript, EvalVerifyResult,
};
#[cfg(feature = "transcript-merlin")]
pub use transcript::MerlinTranscript;
#[cfg(feature = "transcript-blake2b")]
pub use transcript::Blake2bTranscript;
use binary_fields::BinaryFieldElement;
#[cfg(feature = "std")]
#[derive(Debug, thiserror::Error)]
pub enum LigeritoError {
#[error("Invalid configuration: {0}")]
InvalidConfig(String),
#[error("Proof verification failed")]
VerificationFailed,
#[error("Invalid proof structure")]
InvalidProof,
#[error("Merkle tree error: {0}")]
MerkleError(String),
#[error("Sumcheck consistency error: {0}")]
SumcheckError(String),
#[error("GPU initialization failed: {0}")]
GpuInitFailed(String),
}
#[cfg(not(feature = "std"))]
#[derive(Debug, Clone)]
pub enum LigeritoError {
InvalidConfig,
VerificationFailed,
InvalidProof,
MerkleError,
SumcheckError,
GpuInitFailed,
}
#[cfg(not(feature = "std"))]
impl core::fmt::Display for LigeritoError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
LigeritoError::InvalidConfig => write!(f, "Invalid configuration"),
LigeritoError::VerificationFailed => write!(f, "Proof verification failed"),
LigeritoError::InvalidProof => write!(f, "Invalid proof structure"),
LigeritoError::MerkleError => write!(f, "Merkle tree error"),
LigeritoError::SumcheckError => write!(f, "Sumcheck consistency error"),
LigeritoError::GpuInitFailed => write!(f, "GPU initialization failed"),
}
}
}
pub type Result<T> = core::result::Result<T, LigeritoError>;
#[cfg(feature = "prover")]
pub fn prover<T, U>(config: &ProverConfig<T, U>, poly: &[T]) -> Result<FinalizedLigeritoProof<T, U>>
where
T: BinaryFieldElement + Send + Sync + bytemuck::Pod + 'static,
U: BinaryFieldElement + Send + Sync + From<T> + bytemuck::Pod + 'static,
{
prover::prove(config, poly)
}
pub fn verifier<T, U>(config: &VerifierConfig, proof: &FinalizedLigeritoProof<T, U>) -> Result<bool>
where
T: BinaryFieldElement + Send + Sync,
U: BinaryFieldElement + Send + Sync + From<T>,
{
verifier::verify(config, proof)
}
#[cfg(all(test, feature = "std", feature = "prover"))]
mod tests {
use super::*;
use ligerito_binary_fields::{BinaryElem128, BinaryElem32};
#[test]
fn test_basic_prove_verify_merlin() {
let config = hardcoded_config_20(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let mut poly = vec![BinaryElem32::zero(); 1 << 20];
poly[0] = BinaryElem32::one();
println!("Testing with constant polynomial f(x) = 1");
let proof = prover(&config, &poly).unwrap();
println!("Proof generated successfully");
let verifier_config = hardcoded_config_20_verifier();
let result = verifier(&verifier_config, &proof).unwrap();
println!("Verification result: {}", result);
assert!(result);
}
#[test]
fn test_simple_polynomial() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let poly: Vec<BinaryElem32> = vec![BinaryElem32::one(); 1 << 12];
println!("Testing with all-ones polynomial");
let proof = prover(&config, &poly).unwrap();
let verifier_config = hardcoded_config_12_verifier();
let result = verifier(&verifier_config, &proof).unwrap();
assert!(result);
}
#[test]
fn test_zero_polynomial() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let poly: Vec<BinaryElem32> = vec![BinaryElem32::zero(); 1 << 12];
println!("Testing with zero polynomial");
let proof = prover(&config, &poly).unwrap();
let verifier_config = hardcoded_config_12_verifier();
let result = verifier(&verifier_config, &proof).unwrap();
assert!(result);
}
#[test]
fn test_random_polynomial() {
use rand::{thread_rng, Rng};
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let mut rng = thread_rng();
let poly: Vec<BinaryElem32> = (0..1 << 12)
.map(|_| BinaryElem32::from(rng.gen::<u32>()))
.collect();
println!("Testing with random polynomial");
let proof = prover(&config, &poly).unwrap();
let verifier_config = hardcoded_config_12_verifier();
let result = verifier(&verifier_config, &proof).unwrap();
assert!(result);
}
#[test]
fn test_sha256_transcript_compatibility() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let poly: Vec<BinaryElem32> = vec![BinaryElem32::from(42); 1 << 12];
let proof = prove_sha256(&config, &poly).unwrap();
let verifier_config = hardcoded_config_12_verifier();
let result = verify_sha256(&verifier_config, &proof).unwrap();
assert!(result);
}
#[test]
fn test_debug_verification() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let poly: Vec<BinaryElem32> = (0..(1 << 12))
.map(|i| BinaryElem32::from(i as u32))
.collect();
let proof = prover(&config, &poly).unwrap();
let verifier_config = hardcoded_config_12_verifier();
let result = verify_debug(&verifier_config, &proof).unwrap();
assert!(result);
}
#[test]
fn test_proof_size_reasonable() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let poly: Vec<BinaryElem32> = vec![BinaryElem32::one(); 1 << 12];
let proof = prover(&config, &poly).unwrap();
let proof_size = proof.size_of();
println!("Proof size for 2^12 polynomial: {} bytes", proof_size);
let poly_size = poly.len() * std::mem::size_of::<BinaryElem32>();
assert!(
proof_size < poly_size * 3,
"proof should be reasonable size (< 3x polynomial)"
);
assert!(proof_size < 100_000, "proof for 2^12 should be under 100KB");
}
#[test]
fn test_consistency_across_multiple_runs() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let verifier_config = hardcoded_config_12_verifier();
let poly: Vec<BinaryElem32> = vec![BinaryElem32::from(999); 1 << 12];
for i in 0..3 {
let proof = prove_sha256(&config, &poly).unwrap();
let result = verify_sha256(&verifier_config, &proof).unwrap();
assert!(result, "Verification failed on run {}", i);
}
}
#[test]
fn test_pattern_polynomials() {
let config = hardcoded_config_12(
std::marker::PhantomData::<BinaryElem32>,
std::marker::PhantomData::<BinaryElem128>,
);
let verifier_config = hardcoded_config_12_verifier();
let patterns = vec![
(0..1 << 12)
.map(|i| {
if i % 2 == 0 {
BinaryElem32::zero()
} else {
BinaryElem32::one()
}
})
.collect(),
(0..1 << 12)
.map(|i| BinaryElem32::from((i & 0xFF) as u32))
.collect(),
{
let mut poly = vec![BinaryElem32::zero(); 1 << 12];
poly[0] = BinaryElem32::one();
poly[100] = BinaryElem32::from(5);
poly[1000] = BinaryElem32::from(255);
poly
},
];
for (i, poly) in patterns.into_iter().enumerate() {
let proof = prover(&config, &poly).unwrap();
let result = verifier(&verifier_config, &proof).unwrap();
assert!(result, "Pattern {} verification failed", i);
}
}
}