use nebu::Goldilocks;
pub use lens::{Commitment, Opening};
#[derive(Clone, Debug)]
pub struct SumcheckPoly {
pub degree: u8,
pub coeffs: Vec<Goldilocks>,
}
impl SumcheckPoly {
pub fn eval(&self, x: Goldilocks) -> Goldilocks {
let mut r = Goldilocks::ZERO;
for &c in self.coeffs.iter().rev() {
r = r * x + c;
}
r
}
pub fn eval_0(&self) -> Goldilocks {
self.coeffs.first().copied().unwrap_or(Goldilocks::ZERO)
}
pub fn eval_1(&self) -> Goldilocks {
self.coeffs.iter().copied().fold(Goldilocks::ZERO, |acc, c| acc + c)
}
}
#[derive(Clone, Debug)]
pub struct Proof {
pub commitment: Commitment,
pub matrix_evals: Vec<Goldilocks>,
pub outer_sumcheck_polys: Vec<SumcheckPoly>,
pub sumcheck_polys: Vec<SumcheckPoly>,
pub eval_value: Goldilocks,
pub pcs_opening: Opening,
}
#[derive(Clone, Debug)]
pub struct TraceProof {
pub groups: Vec<(Proof, Accumulator)>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Statement {
pub program_hash: [u8; 32],
pub input_hash: [u8; 32],
pub output_hash: [u8; 32],
pub focus_bound: u64,
}
#[derive(Clone, Debug)]
pub struct ProofParams {
pub security: SecurityLevel,
pub lens: LensBackend,
pub max_trace_log: u32,
}
impl Default for ProofParams {
fn default() -> Self {
Self {
security: SecurityLevel::Sec128,
lens: LensBackend::Brakedown,
max_trace_log: 20,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SecurityLevel {
Sec100,
Sec128,
}
impl SecurityLevel {
pub fn lambda(self) -> usize {
match self {
SecurityLevel::Sec100 => 100,
SecurityLevel::Sec128 => 128,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LensBackend {
Brakedown,
Binius,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SparseMatrix {
pub rows: usize,
pub cols: usize,
pub entries: Vec<Vec<(usize, Goldilocks)>>,
}
impl SparseMatrix {
pub fn new(rows: usize, cols: usize) -> Self {
Self { rows, cols, entries: vec![vec![]; rows] }
}
pub fn set(&mut self, row: usize, col: usize, val: Goldilocks) {
self.entries[row].push((col, val));
}
pub fn mul_vec(&self, z: &[Goldilocks]) -> Vec<Goldilocks> {
let mut out = vec![Goldilocks::ZERO; self.rows];
for (i, row) in self.entries.iter().enumerate() {
for &(j, c) in row {
out[i] += c * z.get(j).copied().unwrap_or(Goldilocks::ZERO);
}
}
out
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct CCSInstance {
pub matrices: Vec<SparseMatrix>,
pub multisets: Vec<Vec<usize>>,
pub coeffs: Vec<Goldilocks>,
pub num_rows: usize,
pub num_cols: usize,
}
impl CCSInstance {
pub fn is_satisfied_by(&self, witness: &CCSWitness) -> bool {
let z = &witness.z;
let mut sum = vec![Goldilocks::ZERO; self.num_rows];
for (multiset, &coeff) in self.multisets.iter().zip(self.coeffs.iter()) {
let mut product = vec![Goldilocks::ONE; self.num_rows];
for &idx in multiset {
let mv = self.matrices[idx].mul_vec(z);
for (p, m) in product.iter_mut().zip(mv.iter()) {
*p *= *m;
}
}
for (s, p) in sum.iter_mut().zip(product.iter()) {
*s += coeff * *p;
}
}
sum.iter().all(|&v| v == Goldilocks::ZERO)
}
}
#[derive(Clone, Debug)]
pub struct CCSWitness {
pub z: Vec<Goldilocks>,
}
#[derive(Clone, Debug)]
pub struct Accumulator {
pub committed_instance: CCSInstance,
pub folded_witness: CCSWitness,
pub witness_commitment: Commitment,
pub error_evals: Vec<Goldilocks>,
pub step_count: u64,
}
#[derive(Debug)]
pub enum CommitError {
ExecutionFailed(nox::ErrorKind),
FocusExhausted,
TraceOverflow,
StatementMismatch,
DecideFailed(DecideError),
}
#[derive(Debug)]
pub enum OpenError {
InvalidPoint,
LensFailed,
}
#[derive(Debug)]
pub enum VerifyError {
SumcheckFailed { round: usize },
EvaluationMismatch,
LensFailed,
}
#[derive(Debug)]
pub enum FoldError {
InstanceMismatch,
WitnessMismatch,
}
#[derive(Debug)]
pub enum DecideError {
EmptyAccumulator,
SumcheckFailed { round: usize },
LensFailed,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mul_vec_oob_column_returns_zero() {
let mut m = SparseMatrix::new(1, 10);
m.set(0, 5, Goldilocks::ONE); m.set(0, 9, Goldilocks::new(2)); let z = vec![Goldilocks::ONE; 4];
let result = m.mul_vec(&z);
assert_eq!(result[0], Goldilocks::ZERO);
}
}