mirror of
https://github.com/arnaucube/nova-study.git
synced 2026-01-11 00:21:29 +01:00
Implement poseidon based Transcript & integrate it
- remove Merlin based transcript - implement poseidon based Transcript - implement TranscriptVar gadget - update transcript usage in the other modules to new Transcript interface
This commit is contained in:
@@ -239,6 +239,7 @@ mod test {
|
||||
|
||||
use crate::nifs;
|
||||
use crate::pedersen;
|
||||
use crate::transcript::poseidon_test_config;
|
||||
use ark_ec::CurveGroup;
|
||||
// use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
|
||||
use crate::pedersen::Commitment;
|
||||
@@ -270,6 +271,7 @@ mod test {
|
||||
fn test_nifs_gadget() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
let pedersen_params = pedersen::Pedersen::<MNT6G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
|
||||
let poseidon_config = poseidon_test_config::<Fq>();
|
||||
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
|
||||
@@ -280,7 +282,9 @@ mod test {
|
||||
|
||||
let fw1 = nifs::FWit::<MNT6G1Projective>::new(w1.clone(), A.len());
|
||||
let fw2 = nifs::FWit::<MNT6G1Projective>::new(w2.clone(), A.len());
|
||||
let mut transcript_p = Transcript::<Fq>::new();
|
||||
|
||||
let mut transcript_p = Transcript::<Fq, MNT6G1Projective>::new(&poseidon_config);
|
||||
|
||||
let (fw3, phi1, phi2, T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
|
||||
&mut transcript_p,
|
||||
&pedersen_params,
|
||||
@@ -304,6 +308,6 @@ mod test {
|
||||
let valid = NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(
|
||||
rVar, cmTVar, phi1Var, phi2Var, phi3Var,
|
||||
);
|
||||
println!("num_constraints={:?}", cs.num_constraints());
|
||||
// println!("num_constraints={:?}", cs.num_constraints());
|
||||
}
|
||||
}
|
||||
|
||||
39
src/nifs.rs
39
src/nifs.rs
@@ -1,5 +1,5 @@
|
||||
// use ark_ec::AffineRepr;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_ec::{CurveGroup, Group};
|
||||
use ark_ff::fields::PrimeField;
|
||||
use ark_std::{
|
||||
rand::{Rng, RngCore},
|
||||
@@ -11,6 +11,7 @@ use std::marker::PhantomData;
|
||||
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
||||
use crate::transcript::Transcript;
|
||||
use crate::utils::*;
|
||||
use ark_crypto_primitives::sponge::Absorb;
|
||||
|
||||
pub struct R1CS<F: PrimeField> {
|
||||
pub A: Vec<Vec<F>>,
|
||||
@@ -35,7 +36,11 @@ pub struct FWit<C: CurveGroup> {
|
||||
rW: C::ScalarField,
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> FWit<C> {
|
||||
impl<C: CurveGroup> FWit<C>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
pub fn new(z: Vec<C::ScalarField>, e_len: usize) -> Self {
|
||||
FWit::<C> {
|
||||
E: vec![C::ScalarField::zero(); e_len],
|
||||
@@ -60,7 +65,11 @@ pub struct NIFS<C: CurveGroup> {
|
||||
_phantom: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> NIFS<C> {
|
||||
impl<C: CurveGroup> NIFS<C>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
// comp_T: compute cross-terms T
|
||||
pub fn comp_T(
|
||||
r1cs: &R1CS<C::ScalarField>,
|
||||
@@ -138,7 +147,7 @@ impl<C: CurveGroup> NIFS<C> {
|
||||
|
||||
// NIFS.P
|
||||
pub fn P(
|
||||
tr: &mut Transcript<C::ScalarField>,
|
||||
tr: &mut Transcript<C::ScalarField, C>,
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
r: C::ScalarField,
|
||||
r1cs: &R1CS<C::ScalarField>,
|
||||
@@ -151,7 +160,7 @@ impl<C: CurveGroup> NIFS<C> {
|
||||
|
||||
// compute cross terms
|
||||
let T = Self::comp_T(&r1cs, phi1.u, phi2.u, &fw1.W, &fw2.W);
|
||||
let rT = tr.get_challenge(b"rT");
|
||||
let rT = tr.get_challenge(); // r_T
|
||||
let cmT = Pedersen::commit(&pedersen_params, &T, &rT);
|
||||
|
||||
// fold witness
|
||||
@@ -193,7 +202,7 @@ impl<C: CurveGroup> NIFS<C> {
|
||||
}
|
||||
|
||||
pub fn open_commitments(
|
||||
tr: &mut Transcript<C::ScalarField>,
|
||||
tr: &mut Transcript<C::ScalarField, C>,
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
fw: &FWit<C>,
|
||||
phi: &Phi<C>,
|
||||
@@ -207,7 +216,7 @@ impl<C: CurveGroup> NIFS<C> {
|
||||
(cmE_proof, cmW_proof, cmT_proof)
|
||||
}
|
||||
pub fn verify_commitments(
|
||||
tr: &mut Transcript<C::ScalarField>,
|
||||
tr: &mut Transcript<C::ScalarField, C>,
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
phi: Phi<C>,
|
||||
cmT: Commitment<C>,
|
||||
@@ -273,6 +282,7 @@ pub fn gen_test_values<R: Rng, F: PrimeField>(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::pedersen::Pedersen;
|
||||
use crate::transcript::poseidon_test_config;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_mnt4_298::{Fr, G1Projective};
|
||||
use ark_std::{
|
||||
@@ -287,6 +297,7 @@ mod tests {
|
||||
fn test_one_fold() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
let (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng);
|
||||
let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
|
||||
@@ -329,9 +340,9 @@ mod tests {
|
||||
assert!(NIFS::<G1Projective>::verify(r, &phi1, &phi2, &phi3, &cmT));
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
// check openings of phi3.cmE, phi3.cmW and cmT
|
||||
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
||||
@@ -359,6 +370,7 @@ mod tests {
|
||||
fn test_two_fold() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 6);
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
let (r1cs, w1, w2, w3, x1, x2, x3) = gen_test_values(&mut rng);
|
||||
|
||||
@@ -433,9 +445,9 @@ mod tests {
|
||||
assert_eq!(phi_123_expected.cmW.0, phi_123.cmW.0);
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
// check openings of phi_123.cmE, phi_123.cmW and cmT_123
|
||||
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
||||
@@ -463,6 +475,7 @@ mod tests {
|
||||
fn test_nifs_interface() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
let (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng);
|
||||
let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
|
||||
@@ -473,14 +486,14 @@ mod tests {
|
||||
let fw2 = FWit::<G1Projective>::new(w2.clone(), A.len());
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
// NIFS.P
|
||||
let (fw3, phi1, phi2, T, cmT) =
|
||||
NIFS::<G1Projective>::P(&mut transcript_p, &pedersen_params, r, &r1cs, fw1, fw2);
|
||||
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
// NIFS.V
|
||||
let phi3 = NIFS::<G1Projective>::V(r, &phi1, &phi2, &cmT);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
use ark_ec::AffineRepr;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_ec::{CurveGroup, Group};
|
||||
use ark_std::{
|
||||
rand::{Rng, RngCore},
|
||||
UniformRand,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::transcript::Transcript;
|
||||
use crate::utils::{naive_msm, vec_add, vector_elem_product};
|
||||
|
||||
use crate::transcript::Transcript;
|
||||
use ark_crypto_primitives::sponge::Absorb;
|
||||
use ark_ff::PrimeField;
|
||||
|
||||
pub struct Proof_elem<C: CurveGroup> {
|
||||
R: C,
|
||||
t1: C::ScalarField,
|
||||
@@ -26,11 +29,19 @@ pub struct Params<C: CurveGroup> {
|
||||
pub generators: Vec<C>,
|
||||
}
|
||||
|
||||
pub struct Pedersen<C: CurveGroup> {
|
||||
_phantom: PhantomData<C>,
|
||||
pub struct Pedersen<C: CurveGroup>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
_c: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> Pedersen<C> {
|
||||
impl<C: CurveGroup> Pedersen<C>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
|
||||
let h_scalar = C::ScalarField::rand(rng);
|
||||
let g: C = C::generator();
|
||||
@@ -63,19 +74,19 @@ impl<C: CurveGroup> Pedersen<C> {
|
||||
|
||||
pub fn prove_elem(
|
||||
params: &Params<C>,
|
||||
transcript: &mut Transcript<C::ScalarField>,
|
||||
transcript: &mut Transcript<C::ScalarField, C>,
|
||||
cm: C,
|
||||
v: C::ScalarField,
|
||||
r: C::ScalarField,
|
||||
) -> Proof_elem<C> {
|
||||
let r1 = transcript.get_challenge(b"r_1");
|
||||
let r2 = transcript.get_challenge(b"r_2");
|
||||
let r1 = transcript.get_challenge();
|
||||
let r2 = transcript.get_challenge();
|
||||
|
||||
let R: C = (params.g.mul(r1) + params.h.mul(r2));
|
||||
|
||||
transcript.add(b"cm", &cm);
|
||||
transcript.add(b"R", &R);
|
||||
let e = transcript.get_challenge(b"e");
|
||||
transcript.add_point(&cm);
|
||||
transcript.add_point(&R);
|
||||
let e = transcript.get_challenge();
|
||||
|
||||
let t1 = r1 + v * e;
|
||||
let t2 = r2 + r * e;
|
||||
@@ -84,19 +95,19 @@ impl<C: CurveGroup> Pedersen<C> {
|
||||
}
|
||||
pub fn prove(
|
||||
params: &Params<C>,
|
||||
transcript: &mut Transcript<C::ScalarField>,
|
||||
transcript: &mut Transcript<C::ScalarField, C>,
|
||||
cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
|
||||
v: &Vec<C::ScalarField>,
|
||||
r: &C::ScalarField,
|
||||
) -> Proof<C> {
|
||||
let r1 = transcript.get_challenge(b"r_1");
|
||||
let d = transcript.get_challenge_vec(b"d", v.len());
|
||||
let r1 = transcript.get_challenge();
|
||||
let d = transcript.get_challenge_vec(v.len());
|
||||
|
||||
let R: C = params.h.mul(r1) + naive_msm(&d, ¶ms.generators);
|
||||
|
||||
transcript.add(b"cm", &cm.0);
|
||||
transcript.add(b"R", &R);
|
||||
let e = transcript.get_challenge(b"e");
|
||||
transcript.add_point(&cm.0);
|
||||
transcript.add_point(&R);
|
||||
let e = transcript.get_challenge();
|
||||
|
||||
let u_ = vec_add(&vector_elem_product(&v, &e), &d);
|
||||
let ru_ = e * r + r1;
|
||||
@@ -105,17 +116,17 @@ impl<C: CurveGroup> Pedersen<C> {
|
||||
}
|
||||
pub fn verify(
|
||||
params: &Params<C>,
|
||||
transcript: &mut Transcript<C::ScalarField>,
|
||||
transcript: &mut Transcript<C::ScalarField, C>,
|
||||
cm: Commitment<C>,
|
||||
proof: Proof<C>,
|
||||
) -> bool {
|
||||
// r1, d just to match Prover's transcript
|
||||
transcript.get_challenge(b"r_1");
|
||||
transcript.get_challenge_vec(b"d", proof.u_.len());
|
||||
transcript.get_challenge(); // r_1
|
||||
transcript.get_challenge_vec(proof.u_.len()); // d
|
||||
|
||||
transcript.add(b"cm", &cm.0);
|
||||
transcript.add(b"R", &proof.R);
|
||||
let e = transcript.get_challenge(b"e");
|
||||
transcript.add_point(&cm.0);
|
||||
transcript.add_point(&proof.R);
|
||||
let e = transcript.get_challenge();
|
||||
let lhs = proof.R + cm.0.mul(e);
|
||||
let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, ¶ms.generators);
|
||||
if lhs != rhs {
|
||||
@@ -126,17 +137,17 @@ impl<C: CurveGroup> Pedersen<C> {
|
||||
|
||||
pub fn verify_elem(
|
||||
params: &Params<C>,
|
||||
transcript: &mut Transcript<C::ScalarField>,
|
||||
transcript: &mut Transcript<C::ScalarField, C>,
|
||||
cm: C,
|
||||
proof: Proof_elem<C>,
|
||||
) -> bool {
|
||||
// s1, s2 just to match Prover's transcript
|
||||
transcript.get_challenge(b"r_1");
|
||||
transcript.get_challenge(b"r_2");
|
||||
transcript.get_challenge(); // r_1
|
||||
transcript.get_challenge(); // r_2
|
||||
|
||||
transcript.add(b"cm", &cm);
|
||||
transcript.add(b"R", &proof.R);
|
||||
let e = transcript.get_challenge(b"e");
|
||||
transcript.add_point(&cm);
|
||||
transcript.add_point(&proof.R);
|
||||
let e = transcript.get_challenge();
|
||||
let lhs = proof.R + cm.mul(e);
|
||||
let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
|
||||
if lhs != rhs {
|
||||
@@ -153,11 +164,15 @@ pub struct CommitmentElem<C: CurveGroup> {
|
||||
pub cm: C,
|
||||
pub r: C::ScalarField,
|
||||
}
|
||||
impl<C: CurveGroup> CommitmentElem<C> {
|
||||
impl<C: CurveGroup> CommitmentElem<C>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
pub fn prove(
|
||||
&self,
|
||||
params: &Params<C>,
|
||||
transcript: &mut Transcript<C::ScalarField>,
|
||||
transcript: &mut Transcript<C::ScalarField, C>,
|
||||
v: C::ScalarField,
|
||||
) -> Proof_elem<C> {
|
||||
Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
|
||||
@@ -167,6 +182,7 @@ impl<C: CurveGroup> CommitmentElem<C> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::transcript::poseidon_test_config;
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_mnt4_298::{Fr, G1Projective};
|
||||
use std::ops::Mul;
|
||||
@@ -179,11 +195,12 @@ mod tests {
|
||||
let params = Pedersen::<G1Projective>::new_params(
|
||||
&mut rng, 0, /* 0, as here we don't use commit_vec */
|
||||
);
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
let v = Fr::rand(&mut rng);
|
||||
|
||||
@@ -201,11 +218,12 @@ mod tests {
|
||||
const n: usize = 10;
|
||||
// setup params
|
||||
let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
|
||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||
|
||||
let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
|
||||
let r: Fr = Fr::rand(&mut rng);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// this file contains a sum-check protocol initial implementation, not used by the rest of the repo
|
||||
// but implemented as an exercise and it will probably be used in the future.
|
||||
|
||||
use ark_ec::{CurveGroup, Group};
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
use ark_poly::{
|
||||
multivariate::{SparsePolynomial, SparseTerm, Term},
|
||||
@@ -14,23 +15,30 @@ use ark_std::marker::PhantomData;
|
||||
use ark_std::ops::Mul;
|
||||
use ark_std::{rand::Rng, UniformRand};
|
||||
|
||||
use ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb};
|
||||
|
||||
use crate::transcript::Transcript;
|
||||
|
||||
pub struct SumCheck<
|
||||
F: PrimeField,
|
||||
F: PrimeField + Absorb,
|
||||
C: CurveGroup,
|
||||
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
||||
MV: Polynomial<F> + DenseMVPolynomial<F>,
|
||||
> {
|
||||
_f: PhantomData<F>,
|
||||
_c: PhantomData<C>,
|
||||
_uv: PhantomData<UV>,
|
||||
_mv: PhantomData<MV>,
|
||||
}
|
||||
|
||||
impl<
|
||||
F: PrimeField,
|
||||
F: PrimeField + Absorb,
|
||||
C: CurveGroup,
|
||||
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
||||
MV: Polynomial<F> + DenseMVPolynomial<F>,
|
||||
> SumCheck<F, UV, MV>
|
||||
> SumCheck<F, C, UV, MV>
|
||||
where
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
fn partial_evaluate(g: &MV, point: &[Option<F>]) -> UV {
|
||||
assert!(point.len() >= g.num_vars(), "Invalid evaluation domain");
|
||||
@@ -121,12 +129,12 @@ impl<
|
||||
p
|
||||
}
|
||||
|
||||
pub fn prove(g: MV) -> (F, Vec<UV>, F)
|
||||
pub fn prove(poseidon_config: &PoseidonConfig<F>, g: MV) -> (F, Vec<UV>, F)
|
||||
where
|
||||
<MV as Polynomial<F>>::Point: From<Vec<F>>,
|
||||
{
|
||||
// init transcript
|
||||
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
||||
let mut transcript = Transcript::<F, C>::new(poseidon_config);
|
||||
|
||||
let v = g.num_vars();
|
||||
|
||||
@@ -137,12 +145,12 @@ impl<
|
||||
|
||||
H = H + g.evaluate(&p.into());
|
||||
}
|
||||
transcript.add(b"H", &H);
|
||||
transcript.add(&H);
|
||||
|
||||
let mut ss: Vec<UV> = Vec::new();
|
||||
let mut r: Vec<F> = vec![];
|
||||
for i in 0..v {
|
||||
let r_i = transcript.get_challenge(b"r_i");
|
||||
let r_i = transcript.get_challenge();
|
||||
r.push(r_i);
|
||||
|
||||
let var_slots = v - 1 - i;
|
||||
@@ -153,7 +161,7 @@ impl<
|
||||
let point = Self::point(r[..i].to_vec(), true, v, j);
|
||||
s_i = s_i + Self::partial_evaluate(&g, &point);
|
||||
}
|
||||
transcript.add(b"s_i", &s_i);
|
||||
transcript.add_vec(s_i.coeffs());
|
||||
ss.push(s_i);
|
||||
}
|
||||
|
||||
@@ -161,10 +169,10 @@ impl<
|
||||
(H, ss, last_g_eval)
|
||||
}
|
||||
|
||||
pub fn verify(proof: (F, Vec<UV>, F)) -> bool {
|
||||
pub fn verify(poseidon_config: &PoseidonConfig<F>, proof: (F, Vec<UV>, F)) -> bool {
|
||||
// init transcript
|
||||
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
||||
transcript.add(b"H", &proof.0);
|
||||
let mut transcript = Transcript::<F, C>::new(poseidon_config);
|
||||
transcript.add(&proof.0);
|
||||
|
||||
let (c, ss, last_g_eval) = proof;
|
||||
|
||||
@@ -175,18 +183,18 @@ impl<
|
||||
if c != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
||||
return false;
|
||||
}
|
||||
let r_i = transcript.get_challenge(b"r_i");
|
||||
let r_i = transcript.get_challenge();
|
||||
r.push(r_i);
|
||||
transcript.add(b"s_i", s);
|
||||
transcript.add_vec(s.coeffs());
|
||||
continue;
|
||||
}
|
||||
|
||||
let r_i = transcript.get_challenge(b"r_i");
|
||||
let r_i = transcript.get_challenge();
|
||||
r.push(r_i);
|
||||
if ss[i - 1].evaluate(&r[i - 1]) != s.evaluate(&F::zero()) + s.evaluate(&F::one()) {
|
||||
return false;
|
||||
}
|
||||
transcript.add(b"s_i", s);
|
||||
transcript.add_vec(s.coeffs());
|
||||
}
|
||||
// last round
|
||||
if ss[ss.len() - 1].evaluate(&r[r.len() - 1]) != last_g_eval {
|
||||
@@ -200,14 +208,15 @@ impl<
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ark_mnt4_298::Fr; // scalar field
|
||||
use crate::transcript::poseidon_test_config;
|
||||
use ark_mnt4_298::{Fr, G1Projective}; // scalar field
|
||||
|
||||
#[test]
|
||||
fn test_new_point() {
|
||||
let f4 = Fr::from(4_u32);
|
||||
let f1 = Fr::from(1);
|
||||
let f0 = Fr::from(0);
|
||||
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
type SC = SumCheck<Fr, G1Projective, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
|
||||
let p = SC::point(vec![Fr::from(4_u32)], true, 5, 0);
|
||||
assert_eq!(vec![Some(f4), None, Some(f0), Some(f0), Some(f0),], p);
|
||||
@@ -265,7 +274,7 @@ mod tests {
|
||||
];
|
||||
let p = SparsePolynomial::from_coefficients_slice(3, &terms);
|
||||
|
||||
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
type SC = SumCheck<Fr, G1Projective, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
|
||||
let e0 = SC::partial_evaluate(&p, &[Some(Fr::from(2_u32)), None, Some(Fr::from(0_u32))]);
|
||||
assert_eq!(e0.coeffs(), vec![Fr::from(16_u32)]);
|
||||
@@ -293,13 +302,14 @@ mod tests {
|
||||
let p = SparsePolynomial::from_coefficients_slice(3, &terms);
|
||||
// println!("p {:?}", p);
|
||||
|
||||
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
type SC = SumCheck<Fr, G1Projective, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
|
||||
let proof = SC::prove(p);
|
||||
let proof = SC::prove(&poseidon_config, p);
|
||||
assert_eq!(proof.0, Fr::from(12_u32));
|
||||
// println!("proof {:?}", proof);
|
||||
|
||||
let v = SC::verify(proof);
|
||||
let v = SC::verify(&poseidon_config, proof);
|
||||
assert!(v);
|
||||
}
|
||||
|
||||
@@ -335,12 +345,13 @@ mod tests {
|
||||
let p = rand_poly(3, 3, &mut rng);
|
||||
// println!("p {:?}", p);
|
||||
|
||||
type SC = SumCheck<Fr, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
type SC = SumCheck<Fr, G1Projective, DensePolynomial<Fr>, SparsePolynomial<Fr, SparseTerm>>;
|
||||
|
||||
let proof = SC::prove(p);
|
||||
println!("proof.s len {:?}", proof.1.len());
|
||||
let proof = SC::prove(&poseidon_config, p);
|
||||
// println!("proof.s len {:?}", proof.1.len());
|
||||
|
||||
let v = SC::verify(proof);
|
||||
let v = SC::verify(&poseidon_config, proof);
|
||||
assert!(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,125 @@
|
||||
use ark_ec::{AffineRepr, CurveGroup, Group};
|
||||
use ark_ff::PrimeField;
|
||||
use ark_serialize::CanonicalSerialize;
|
||||
use merlin::Transcript as MerlinTranscript;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
// TODO poseidon transcript (not keccak)
|
||||
use ark_r1cs_std::fields::fp::FpVar;
|
||||
|
||||
// This Transcript approach is a modified version from https://github.com/arkworks-rs/gemini ,
|
||||
// using Merlin transcript (https://merlin.cool).
|
||||
pub struct Transcript<F: PrimeField> {
|
||||
phantom: PhantomData<F>,
|
||||
transcript: MerlinTranscript,
|
||||
use ark_crypto_primitives::sponge::poseidon::{
|
||||
constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
|
||||
};
|
||||
use ark_crypto_primitives::sponge::{
|
||||
constraints::CryptographicSpongeVar, Absorb, CryptographicSponge,
|
||||
};
|
||||
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
||||
|
||||
use ark_poly::DenseUVPolynomial;
|
||||
|
||||
pub struct Transcript<F: PrimeField + Absorb, C: CurveGroup>
|
||||
where
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
// where F is the Constraint Field (eq. C::ScalarField)
|
||||
sponge: PoseidonSponge<F>,
|
||||
_c: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField> Transcript<F> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
phantom: PhantomData::default(),
|
||||
transcript: MerlinTranscript::new(b"transcript"),
|
||||
impl<F: PrimeField + Absorb, C: CurveGroup> Transcript<F, C>
|
||||
where
|
||||
<C as CurveGroup>::BaseField: Absorb,
|
||||
{
|
||||
pub fn new(poseidon_config: &PoseidonConfig<F>) -> Self {
|
||||
let mut sponge = PoseidonSponge::<F>::new(&poseidon_config);
|
||||
Transcript {
|
||||
sponge,
|
||||
_c: PhantomData,
|
||||
}
|
||||
}
|
||||
pub fn add<S: CanonicalSerialize>(&mut self, label: &'static [u8], r: &S) {
|
||||
let mut msg = Vec::new();
|
||||
r.serialize_uncompressed(&mut msg).unwrap();
|
||||
self.transcript.append_message(label, &msg);
|
||||
pub fn add(&mut self, v: &F) {
|
||||
self.sponge.absorb(&v);
|
||||
}
|
||||
pub fn get_challenge(&mut self, label: &'static [u8]) -> F {
|
||||
let mut bytes = [0u8; 64];
|
||||
self.transcript.challenge_bytes(label, &mut bytes);
|
||||
let challenge = F::from_le_bytes_mod_order(bytes.as_ref());
|
||||
self.add(b"get challenge", &challenge);
|
||||
challenge
|
||||
pub fn add_vec(&mut self, v: &[F]) {
|
||||
self.sponge.absorb(&v);
|
||||
}
|
||||
pub fn get_challenge_vec(&mut self, label: &'static [u8], n: usize) -> Vec<F> {
|
||||
let mut c: Vec<F> = vec![F::zero(); n];
|
||||
for i in 0..n {
|
||||
c[i] = self.get_challenge(label);
|
||||
}
|
||||
pub fn add_point(&mut self, v: &C) {
|
||||
let v_affine = v.into_affine();
|
||||
let xy = v_affine.xy().unwrap(); // WIP
|
||||
self.sponge.absorb(&vec![xy.0, xy.1]);
|
||||
}
|
||||
pub fn get_challenge(&mut self) -> F {
|
||||
let c = self.sponge.squeeze_field_elements(1);
|
||||
self.add(&c[0]);
|
||||
c[0]
|
||||
}
|
||||
pub fn get_challenge_vec(&mut self, n: usize) -> Vec<F> {
|
||||
let c = self.sponge.squeeze_field_elements(n);
|
||||
self.sponge.absorb(&c);
|
||||
c
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TranscriptVar<F: PrimeField> {
|
||||
// where F is the Constraint Field
|
||||
sponge: PoseidonSpongeVar<F>,
|
||||
}
|
||||
impl<F: PrimeField> TranscriptVar<F> {
|
||||
pub fn new(cs: ConstraintSystemRef<F>, poseidon_config: PoseidonConfig<F>) -> Self {
|
||||
let mut sponge = PoseidonSpongeVar::<F>::new(cs.clone(), &poseidon_config);
|
||||
Self { sponge }
|
||||
}
|
||||
pub fn add(&mut self, v: FpVar<F>) -> Result<(), SynthesisError> {
|
||||
self.sponge.absorb(&v)
|
||||
}
|
||||
pub fn get_challenge(&mut self) -> Result<FpVar<F>, SynthesisError> {
|
||||
let c = self.sponge.squeeze_field_elements(1)?;
|
||||
self.sponge.absorb(&c[0]);
|
||||
Ok(c[0].clone())
|
||||
}
|
||||
pub fn get_challenge_vec(&mut self, n: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
|
||||
let c = self.sponge.squeeze_field_elements(n)?;
|
||||
self.sponge.absorb(&c);
|
||||
Ok(c)
|
||||
}
|
||||
}
|
||||
|
||||
use ark_crypto_primitives::sponge::poseidon::find_poseidon_ark_and_mds;
|
||||
|
||||
// WARNING this is for test only
|
||||
pub fn poseidon_test_config<F: PrimeField>() -> PoseidonConfig<F> {
|
||||
let full_rounds = 8;
|
||||
let partial_rounds = 31;
|
||||
let alpha = 5;
|
||||
let rate = 2;
|
||||
|
||||
let (ark, mds) = find_poseidon_ark_and_mds::<F>(
|
||||
F::MODULUS_BIT_SIZE as u64,
|
||||
rate,
|
||||
full_rounds,
|
||||
partial_rounds,
|
||||
0,
|
||||
);
|
||||
|
||||
PoseidonConfig::new(
|
||||
full_rounds as usize,
|
||||
partial_rounds as usize,
|
||||
alpha,
|
||||
mds,
|
||||
ark,
|
||||
rate,
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use ark_mnt4_298::{Fr, G1Projective}; // scalar field
|
||||
// use ark_std::{One, Zero};
|
||||
//
|
||||
// #[test]
|
||||
// fn test_poseidon() {
|
||||
// let config = poseidon_test_config::<Fr>();
|
||||
// let mut tr = Transcript::<Fr, G1Projective>::new(&config);
|
||||
// tr.add(&Fr::one());
|
||||
// println!("c {:?}", tr.get_challenge().to_string());
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user