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 { cmE: Commitment, u: C::ScalarField, cmW: Commitment, x: Vec, } // FWit: Folded Witness pub struct FWit { E: Vec, rE: C::ScalarField, W: Vec, rW: C::ScalarField, } pub struct NIFS { _phantom: PhantomData, } impl NIFS { pub fn fold_witness( r: C::ScalarField, fw1: FWit, fw2: FWit, T: Vec, ) -> FWit { let r2 = r * r; let E: Vec = 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:: { E: E.into(), rE, W: W.into(), rW, } } pub fn fold_instance( r: C::ScalarField, phi1: Phi, phi2: Phi, cmT: Commitment, ) -> Phi { 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:: { cmE: Commitment:: { cm: cmE.into(), r: phi1.cmE.r, }, u, cmW: Commitment:: { cm: cmW.into(), r: phi1.cmW.r, }, x, } } }