mirror of
https://github.com/arnaucube/nova-study.git
synced 2026-01-09 23:51:29 +01:00
sumcheck use transcript, reorganize some files
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK};
|
use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK};
|
||||||
|
use ark_ec::AffineRepr;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::CurveGroup;
|
||||||
use ark_ff::{fields::Fp256, Field, PrimeField};
|
use ark_ff::{fields::Fp256, Field, PrimeField};
|
||||||
use ark_r1cs_std::{
|
use ark_r1cs_std::{
|
||||||
@@ -42,8 +43,6 @@ impl<Fq: PrimeField, Fr: PrimeField, C: CurveGroup, GC: CurveVar<C, Fq>, Cfg: Co
|
|||||||
{
|
{
|
||||||
fn generate_constraints(self, cs: ConstraintSystemRef<Fq>) -> Result<(), SynthesisError> {
|
fn generate_constraints(self, cs: ConstraintSystemRef<Fq>) -> Result<(), SynthesisError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
// nifscircuit::NIFSGadget::<Fq, C, GC<Fq, C>>::verify();
|
|
||||||
// hash
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(unused)] // TMP
|
#![allow(unused)] // TMP
|
||||||
|
|
||||||
|
mod circuits;
|
||||||
mod nifs;
|
mod nifs;
|
||||||
mod novacircuit;
|
|
||||||
mod pedersen;
|
mod pedersen;
|
||||||
mod r1cs;
|
mod sumcheck;
|
||||||
mod transcript;
|
mod transcript;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|||||||
20
src/nifs.rs
20
src/nifs.rs
@@ -1,15 +1,21 @@
|
|||||||
use ark_ec::AffineRepr;
|
use ark_ec::AffineRepr;
|
||||||
use ark_std::{One, Zero};
|
use ark_ff::fields::PrimeField;
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
|
||||||
use crate::r1cs::*;
|
|
||||||
use crate::transcript::Transcript;
|
|
||||||
use crate::utils::*;
|
|
||||||
use ark_std::{
|
use ark_std::{
|
||||||
rand::{Rng, RngCore},
|
rand::{Rng, RngCore},
|
||||||
UniformRand,
|
UniformRand,
|
||||||
};
|
};
|
||||||
|
use ark_std::{One, Zero};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
||||||
|
use crate::transcript::Transcript;
|
||||||
|
use crate::utils::*;
|
||||||
|
|
||||||
|
pub struct R1CS<F: PrimeField> {
|
||||||
|
pub A: Vec<Vec<F>>,
|
||||||
|
pub B: Vec<Vec<F>>,
|
||||||
|
pub C: Vec<Vec<F>>,
|
||||||
|
}
|
||||||
|
|
||||||
// Phi: φ in the paper (later 𝖴), a folded instance
|
// Phi: φ in the paper (later 𝖴), a folded instance
|
||||||
pub struct Phi<C: AffineRepr> {
|
pub struct Phi<C: AffineRepr> {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub struct Proof<C: AffineRepr> {
|
|||||||
pub struct Params<C: AffineRepr> {
|
pub struct Params<C: AffineRepr> {
|
||||||
g: C,
|
g: C,
|
||||||
h: C,
|
h: C,
|
||||||
pub r_vec: Vec<C>,
|
pub generators: Vec<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pedersen<C: AffineRepr> {
|
pub struct Pedersen<C: AffineRepr> {
|
||||||
@@ -33,11 +33,11 @@ impl<C: AffineRepr> Pedersen<C> {
|
|||||||
pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
|
pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
|
||||||
let h_scalar = C::ScalarField::rand(rng);
|
let h_scalar = C::ScalarField::rand(rng);
|
||||||
let g: C = C::generator();
|
let g: C = C::generator();
|
||||||
let r_vec: Vec<C> = vec![C::rand(rng); max];
|
let generators: Vec<C> = vec![C::rand(rng); max];
|
||||||
let params: Params<C> = Params::<C> {
|
let params: Params<C> = Params::<C> {
|
||||||
g,
|
g,
|
||||||
h: g.mul(h_scalar).into(),
|
h: g.mul(h_scalar).into(),
|
||||||
r_vec, // will need 2 r: rE, rW
|
generators,
|
||||||
};
|
};
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ impl<C: AffineRepr> Pedersen<C> {
|
|||||||
v: &Vec<C::ScalarField>,
|
v: &Vec<C::ScalarField>,
|
||||||
r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
|
r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
|
||||||
) -> Commitment<C> {
|
) -> Commitment<C> {
|
||||||
let cm = params.h.mul(r) + naive_msm(v, ¶ms.r_vec);
|
let cm = params.h.mul(r) + naive_msm(v, ¶ms.generators);
|
||||||
Commitment::<C>(cm.into())
|
Commitment::<C>(cm.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ impl<C: AffineRepr> Pedersen<C> {
|
|||||||
let r1 = transcript.get_challenge(b"r_1");
|
let r1 = transcript.get_challenge(b"r_1");
|
||||||
let d = transcript.get_challenge_vec(b"d", v.len());
|
let d = transcript.get_challenge_vec(b"d", v.len());
|
||||||
|
|
||||||
let R: C = (params.h.mul(r1) + naive_msm(&d, ¶ms.r_vec)).into();
|
let R: C = (params.h.mul(r1) + naive_msm(&d, ¶ms.generators)).into();
|
||||||
|
|
||||||
transcript.add(b"cm", &cm.0);
|
transcript.add(b"cm", &cm.0);
|
||||||
transcript.add(b"R", &R);
|
transcript.add(b"R", &R);
|
||||||
@@ -116,7 +116,7 @@ impl<C: AffineRepr> Pedersen<C> {
|
|||||||
transcript.add(b"R", &proof.R);
|
transcript.add(b"R", &proof.R);
|
||||||
let e = transcript.get_challenge(b"e");
|
let e = transcript.get_challenge(b"e");
|
||||||
let lhs = proof.R + cm.0.mul(e);
|
let lhs = proof.R + cm.0.mul(e);
|
||||||
let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, ¶ms.r_vec);
|
let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, ¶ms.generators);
|
||||||
if lhs != rhs {
|
if lhs != rhs {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/r1cs.rs
34
src/r1cs.rs
@@ -1,34 +0,0 @@
|
|||||||
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!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Sum-check protocol initial implementation, not used by the rest of the repo but implemented as
|
// Sum-check protocol initial implementation, not used by the rest of the repo but implemented as
|
||||||
// an exercise and might be used in the future.
|
// an exercise and it will probably be used in the future.
|
||||||
|
|
||||||
use ark_ff::{BigInteger, PrimeField};
|
use ark_ff::{BigInteger, PrimeField};
|
||||||
use ark_poly::{
|
use ark_poly::{
|
||||||
@@ -14,6 +14,8 @@ use ark_std::marker::PhantomData;
|
|||||||
use ark_std::ops::Mul;
|
use ark_std::ops::Mul;
|
||||||
use ark_std::{rand::Rng, UniformRand};
|
use ark_std::{rand::Rng, UniformRand};
|
||||||
|
|
||||||
|
use crate::transcript::Transcript;
|
||||||
|
|
||||||
pub struct SumCheck<
|
pub struct SumCheck<
|
||||||
F: PrimeField,
|
F: PrimeField,
|
||||||
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
||||||
@@ -81,10 +83,8 @@ impl<
|
|||||||
|
|
||||||
fn point_complete(challenges: Vec<F>, n_elems: usize, iter_num: usize) -> Vec<F> {
|
fn point_complete(challenges: Vec<F>, n_elems: usize, iter_num: usize) -> Vec<F> {
|
||||||
let p = Self::point(challenges, false, n_elems, iter_num);
|
let p = Self::point(challenges, false, n_elems, iter_num);
|
||||||
// let mut r = Vec::new();
|
|
||||||
let mut r = vec![F::zero(); n_elems];
|
let mut r = vec![F::zero(); n_elems];
|
||||||
for i in 0..n_elems {
|
for i in 0..n_elems {
|
||||||
// r.push(p[i].unwrap());
|
|
||||||
r[i] = p[i].unwrap();
|
r[i] = p[i].unwrap();
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
@@ -96,7 +96,7 @@ impl<
|
|||||||
if none {
|
if none {
|
||||||
// WIP
|
// WIP
|
||||||
if n_vars == 0 {
|
if n_vars == 0 {
|
||||||
panic!("err");
|
panic!("err"); // or return directly challenges vector
|
||||||
}
|
}
|
||||||
n_vars -= 1;
|
n_vars -= 1;
|
||||||
}
|
}
|
||||||
@@ -125,9 +125,10 @@ impl<
|
|||||||
where
|
where
|
||||||
<MV as Polynomial<F>>::Point: From<Vec<F>>,
|
<MV as Polynomial<F>>::Point: From<Vec<F>>,
|
||||||
{
|
{
|
||||||
let v = g.num_vars();
|
// init transcript
|
||||||
|
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
||||||
|
|
||||||
let r = vec![F::from(2_u32), F::from(3_u32), F::from(6_u32)]; // TMP will come from transcript
|
let v = g.num_vars();
|
||||||
|
|
||||||
// compute H
|
// compute H
|
||||||
let mut H = F::zero();
|
let mut H = F::zero();
|
||||||
@@ -136,43 +137,56 @@ impl<
|
|||||||
|
|
||||||
H = H + g.evaluate(&p.into());
|
H = H + g.evaluate(&p.into());
|
||||||
}
|
}
|
||||||
|
transcript.add(b"H", &H);
|
||||||
|
|
||||||
let mut ss: Vec<UV> = Vec::new();
|
let mut ss: Vec<UV> = Vec::new();
|
||||||
|
let mut r: Vec<F> = vec![];
|
||||||
for i in 0..v {
|
for i in 0..v {
|
||||||
|
let r_i = transcript.get_challenge(b"r_i");
|
||||||
|
r.push(r_i);
|
||||||
|
|
||||||
let var_slots = v - 1 - i;
|
let var_slots = v - 1 - i;
|
||||||
let n_points = 2_u64.pow(var_slots as u32) as usize;
|
let n_points = 2_u64.pow(var_slots as u32) as usize;
|
||||||
|
|
||||||
let mut s_i = UV::zero();
|
let mut s_i = UV::zero();
|
||||||
let r_round = r.as_slice()[..i].to_vec();
|
|
||||||
for j in 0..n_points {
|
for j in 0..n_points {
|
||||||
let point = Self::point(r_round.clone(), true, v, j);
|
let point = Self::point(r[..i].to_vec(), true, v, j);
|
||||||
s_i = s_i + Self::partial_evaluate(&g, &point);
|
s_i = s_i + Self::partial_evaluate(&g, &point);
|
||||||
}
|
}
|
||||||
|
transcript.add(b"s_i", &s_i);
|
||||||
ss.push(s_i);
|
ss.push(s_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let point_last = r;
|
let last_g_eval = g.evaluate(&r.into());
|
||||||
let last_g_eval = g.evaluate(&point_last.into());
|
|
||||||
(H, ss, last_g_eval)
|
(H, ss, last_g_eval)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(proof: (F, Vec<UV>, F)) -> bool {
|
pub fn verify(proof: (F, Vec<UV>, F)) -> bool {
|
||||||
// let c: F, ss: Vec<UV>;
|
// init transcript
|
||||||
|
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
||||||
|
transcript.add(b"H", &proof.0);
|
||||||
|
|
||||||
let (c, ss, last_g_eval) = proof;
|
let (c, ss, last_g_eval) = proof;
|
||||||
|
|
||||||
let r = vec![F::from(2_u32), F::from(3_u32), F::from(6_u32)]; // TMP will come from transcript
|
let mut r: Vec<F> = vec![];
|
||||||
|
|
||||||
for (i, s) in ss.iter().enumerate() {
|
for (i, s) in ss.iter().enumerate() {
|
||||||
// TODO check degree
|
// TODO check degree
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if c != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
if c != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let r_i = transcript.get_challenge(b"r_i");
|
||||||
|
r.push(r_i);
|
||||||
|
transcript.add(b"s_i", s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let r_i = transcript.get_challenge(b"r_i");
|
||||||
|
r.push(r_i);
|
||||||
if ss[i - 1].evaluate(&r[i - 1]) != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
if ss[i - 1].evaluate(&r[i - 1]) != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
transcript.add(b"s_i", s);
|
||||||
}
|
}
|
||||||
// last round
|
// last round
|
||||||
if ss[ss.len() - 1].evaluate(&r[r.len() - 1]) != last_g_eval {
|
if ss[ss.len() - 1].evaluate(&r[r.len() - 1]) != last_g_eval {
|
||||||
@@ -264,9 +278,6 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_flow_hardcoded_values() {
|
fn test_flow_hardcoded_values() {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
// let p = SparsePolynomial::<Fr, SparseTerm>::rand(deg, 3, &mut rng);
|
|
||||||
// let p = rand_poly(3, 3, &mut rng);
|
|
||||||
|
|
||||||
// g(X_0, X_1, X_2) = 2 X_0^3 + X_0 X_2 + X_1 X_2
|
// g(X_0, X_1, X_2) = 2 X_0^3 + X_0 X_2 + X_1 X_2
|
||||||
let terms = vec![
|
let terms = vec![
|
||||||
(Fr::from(2u32), SparseTerm::new(vec![(0_usize, 3)])),
|
(Fr::from(2u32), SparseTerm::new(vec![(0_usize, 3)])),
|
||||||
@@ -286,17 +297,43 @@ mod tests {
|
|||||||
|
|
||||||
let proof = SC::prove(p);
|
let proof = SC::prove(p);
|
||||||
assert_eq!(proof.0, Fr::from(12_u32));
|
assert_eq!(proof.0, Fr::from(12_u32));
|
||||||
println!("proof {:?}", proof);
|
// println!("proof {:?}", proof);
|
||||||
|
|
||||||
let v = SC::verify(proof);
|
let v = SC::verify(proof);
|
||||||
assert!(v);
|
assert!(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rand_poly<R: Rng>(l: usize, d: usize, rng: &mut R) -> SparsePolynomial<Fr, SparseTerm> {
|
||||||
|
// This method is from the arkworks/algebra/poly/multivariate test:
|
||||||
|
// https://github.com/arkworks-rs/algebra/blob/bc991d44c5e579025b7ed56df3d30267a7b9acac/poly/src/polynomial/multivariate/sparse.rs#L303
|
||||||
|
let mut random_terms = Vec::new();
|
||||||
|
let num_terms = rng.gen_range(1..1000);
|
||||||
|
// For each term, randomly select up to `l` variables with degree
|
||||||
|
// in [1,d] and random coefficient
|
||||||
|
random_terms.push((Fr::rand(rng), SparseTerm::new(vec![])));
|
||||||
|
for _ in 1..num_terms {
|
||||||
|
let term = (0..l)
|
||||||
|
.map(|i| {
|
||||||
|
if rng.gen_bool(0.5) {
|
||||||
|
Some((i, rng.gen_range(1..(d + 1))))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
let coeff = Fr::rand(rng);
|
||||||
|
random_terms.push((coeff, SparseTerm::new(term)));
|
||||||
|
}
|
||||||
|
SparsePolynomial::from_coefficients_slice(l, &random_terms)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flow_rng() {
|
fn test_flow_rng() {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
let p = SparsePolynomial::<Fr, SparseTerm>::rand(3, 3, &mut rng);
|
// let p = SparsePolynomial::<Fr, SparseTerm>::rand(3, 3, &mut rng);
|
||||||
println!("p {:?}", p);
|
let p = rand_poly(3, 3, &mut rng);
|
||||||
|
// println!("p {:?}", p);
|
||||||
|
|
||||||
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use ark_serialize::CanonicalSerialize;
|
|||||||
use merlin::Transcript as MerlinTranscript;
|
use merlin::Transcript as MerlinTranscript;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
// TODO poseidon transcript (not keccak)
|
||||||
|
|
||||||
// This Transcript approach is a modified version from https://github.com/arkworks-rs/gemini ,
|
// This Transcript approach is a modified version from https://github.com/arkworks-rs/gemini ,
|
||||||
// using Merlin transcript (https://merlin.cool).
|
// using Merlin transcript (https://merlin.cool).
|
||||||
pub struct Transcript<F: PrimeField> {
|
pub struct Transcript<F: PrimeField> {
|
||||||
|
|||||||
Reference in New Issue
Block a user