add initial NIFS fold instance & witness
arnaucube root@arnaucube.com
Tue, 18 Apr 2023 12:42:54 +0200
4 files changed,
133 insertions(+),
0 deletions(-)
A
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.
A
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;
A
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, + } + } +}
A
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!(); + } +}