Browse Source

add initial NIFS fold instance & witness

ivc-proofs
arnaucube 1 year ago
parent
commit
050110a4dc
4 changed files with 133 additions and 0 deletions
  1. +9
    -0
      README.md
  2. +10
    -0
      src/lib.rs
  3. +80
    -0
      src/nifs.rs
  4. +34
    -0
      src/r1cs.rs

+ 9
- 0
README.md

@ -0,0 +1,9 @@
# nova-study
Implementation of [Nova](https://eprint.iacr.org/2021/370.pdf) using [arkworks-rs](https://github.com/arkworks-rs/) just for learning purposes.
> Warning: Implementation from scratch to learn the internals of Nova. Do not use in production.
This repo is an ongoing implementation, not to be used but just to understand and experiment with the internals of the scheme and try experimental combinations.
Thanks to [levs57](https://twitter.com/levs57) for clarifications on the Nova folding.

+ 10
- 0
src/lib.rs

@ -0,0 +1,10 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(unused)] // TMP
mod nifs;
mod pedersen;
mod r1cs;
mod transcript;
mod utils;

+ 80
- 0
src/nifs.rs

@ -0,0 +1,80 @@
use ark_ec::AffineRepr;
use ark_std::ops::Add;
use std::marker::PhantomData;
use crate::pedersen::Commitment;
use crate::r1cs::*;
use crate::transcript::Transcript;
use crate::utils::*;
// Phi: φ in the paper (later 𝖴), a folded instance
pub struct Phi<C: AffineRepr> {
cmE: Commitment<C>,
u: C::ScalarField,
cmW: Commitment<C>,
x: Vec<C::ScalarField>,
}
// FWit: Folded Witness
pub struct FWit<C: AffineRepr> {
E: Vec<C::ScalarField>,
rE: C::ScalarField,
W: Vec<C::ScalarField>,
rW: C::ScalarField,
}
pub struct NIFS<C: AffineRepr> {
_phantom: PhantomData<C>,
}
impl<C: AffineRepr> NIFS<C> {
pub fn fold_witness(
r: C::ScalarField,
fw1: FWit<C>,
fw2: FWit<C>,
T: Vec<C::ScalarField>,
) -> FWit<C> {
let r2 = r * r;
let E: Vec<C::ScalarField> = vec_add(
// TODO this syntax will be simplified with future operators impl
vec_add(fw1.E, vector_elem_product(&T, &r)),
vector_elem_product(&fw2.E, &r2),
);
let rE = fw1.rE + r * fw2.rE;
let W = vec_add(fw1.W, vector_elem_product(&fw2.W, &r));
let rW = fw1.rW + r * fw2.rW;
FWit::<C> {
E: E.into(),
rE,
W: W.into(),
rW,
}
}
pub fn fold_instance(
r: C::ScalarField,
phi1: Phi<C>,
phi2: Phi<C>,
cmT: Commitment<C>,
) -> Phi<C> {
let r2 = r * r;
let cmE = phi1.cmE.cm + cmT.cm.mul(r) + phi2.cmE.cm.mul(r2);
let u = phi1.u + r * phi2.u;
let cmW = phi1.cmW.cm + phi2.cmW.cm.mul(r);
let x = vec_add(phi1.x, vector_elem_product(&phi2.x, &r));
Phi::<C> {
cmE: Commitment::<C> {
cm: cmE.into(),
r: phi1.cmE.r,
},
u,
cmW: Commitment::<C> {
cm: cmW.into(),
r: phi1.cmW.r,
},
x,
}
}
}

+ 34
- 0
src/r1cs.rs

@ -0,0 +1,34 @@
use crate::pedersen;
use ark_ff::fields::PrimeField;
use core::ops::Add;
// this file contains an abstraction of R1CS struct, to later be plugged from arkworks
// ConstraintSystem or something similar.
pub struct R1CS<F: PrimeField> {
pub A: Vec<Vec<F>>,
pub B: Vec<Vec<F>>,
pub C: Vec<Vec<F>>,
}
pub struct RelaxedR1CS<F: PrimeField> {
pub ABC: R1CS<F>,
pub u: F,
pub E: F,
}
impl<F: PrimeField> R1CS<F> {
pub fn relax(self) -> RelaxedR1CS<F> {
RelaxedR1CS::<F> {
ABC: self,
u: F::one(),
E: F::zero(),
}
}
}
impl<F: PrimeField> RelaxedR1CS<F> {
pub fn fold(self, other: Self, r: F) -> Self {
unimplemented!();
}
}

Loading…
Cancel
Save