mirror of
https://github.com/arnaucube/nova-study.git
synced 2026-01-10 16:11:30 +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:
@@ -9,4 +9,4 @@ This repo is an ongoing implementation, the code will be dirty for a while and n
|
|||||||
Thanks to [Levs57](https://twitter.com/levs57), [Nalin Bhardwaj](https://twitter.com/nibnalin) and [Carlos Pérez](https://twitter.com/cperezz19) for clarifications on the Nova paper.
|
Thanks to [Levs57](https://twitter.com/levs57), [Nalin Bhardwaj](https://twitter.com/nibnalin) and [Carlos Pérez](https://twitter.com/cperezz19) for clarifications on the Nova paper.
|
||||||
|
|
||||||
### Details
|
### Details
|
||||||
Initial impl using a cycle of pairing-friendly curves with Groth16 for the folding proofs (as an example, the tests use MNT4, MNT6 curves), once the full scheme works, will see how many constraints the folding circuits need and might change one of the sides to a non-pairing curve with a non-pairing proof instead of Groth16. Eventually would like to explore also using BN254 with Grumpkin for ending up verifying the proofs in Ethereum.
|
Current implementation uses a cycle of pairing-friendly curves with Groth16 for the folding proofs (as an example, the tests use MNT4, MNT6 curves), once the full scheme works, will see how many constraints the folding circuits need and might change one of the sides to a non-pairing curve with a non-pairing proof instead of Groth16. Eventually would like to explore also using BN254 with Grumpkin for ending up verifying the proofs in Ethereum.
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ mod test {
|
|||||||
|
|
||||||
use crate::nifs;
|
use crate::nifs;
|
||||||
use crate::pedersen;
|
use crate::pedersen;
|
||||||
|
use crate::transcript::poseidon_test_config;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::CurveGroup;
|
||||||
// use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
|
// use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
|
||||||
use crate::pedersen::Commitment;
|
use crate::pedersen::Commitment;
|
||||||
@@ -270,6 +271,7 @@ mod test {
|
|||||||
fn test_nifs_gadget() {
|
fn test_nifs_gadget() {
|
||||||
let mut rng = ark_std::test_rng();
|
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 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();
|
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||||
|
|
||||||
@@ -280,7 +282,9 @@ mod test {
|
|||||||
|
|
||||||
let fw1 = nifs::FWit::<MNT6G1Projective>::new(w1.clone(), A.len());
|
let fw1 = nifs::FWit::<MNT6G1Projective>::new(w1.clone(), A.len());
|
||||||
let fw2 = nifs::FWit::<MNT6G1Projective>::new(w2.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(
|
let (fw3, phi1, phi2, T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
|
||||||
&mut transcript_p,
|
&mut transcript_p,
|
||||||
&pedersen_params,
|
&pedersen_params,
|
||||||
@@ -304,6 +308,6 @@ mod test {
|
|||||||
let valid = NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(
|
let valid = NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(
|
||||||
rVar, cmTVar, phi1Var, phi2Var, phi3Var,
|
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::AffineRepr;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::{CurveGroup, Group};
|
||||||
use ark_ff::fields::PrimeField;
|
use ark_ff::fields::PrimeField;
|
||||||
use ark_std::{
|
use ark_std::{
|
||||||
rand::{Rng, RngCore},
|
rand::{Rng, RngCore},
|
||||||
@@ -11,6 +11,7 @@ use std::marker::PhantomData;
|
|||||||
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
|
use ark_crypto_primitives::sponge::Absorb;
|
||||||
|
|
||||||
pub struct R1CS<F: PrimeField> {
|
pub struct R1CS<F: PrimeField> {
|
||||||
pub A: Vec<Vec<F>>,
|
pub A: Vec<Vec<F>>,
|
||||||
@@ -35,7 +36,11 @@ pub struct FWit<C: CurveGroup> {
|
|||||||
rW: C::ScalarField,
|
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 {
|
pub fn new(z: Vec<C::ScalarField>, e_len: usize) -> Self {
|
||||||
FWit::<C> {
|
FWit::<C> {
|
||||||
E: vec![C::ScalarField::zero(); e_len],
|
E: vec![C::ScalarField::zero(); e_len],
|
||||||
@@ -60,7 +65,11 @@ pub struct NIFS<C: CurveGroup> {
|
|||||||
_phantom: PhantomData<C>,
|
_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
|
// comp_T: compute cross-terms T
|
||||||
pub fn comp_T(
|
pub fn comp_T(
|
||||||
r1cs: &R1CS<C::ScalarField>,
|
r1cs: &R1CS<C::ScalarField>,
|
||||||
@@ -138,7 +147,7 @@ impl<C: CurveGroup> NIFS<C> {
|
|||||||
|
|
||||||
// NIFS.P
|
// NIFS.P
|
||||||
pub fn P(
|
pub fn P(
|
||||||
tr: &mut Transcript<C::ScalarField>,
|
tr: &mut Transcript<C::ScalarField, C>,
|
||||||
pedersen_params: &PedersenParams<C>,
|
pedersen_params: &PedersenParams<C>,
|
||||||
r: C::ScalarField,
|
r: C::ScalarField,
|
||||||
r1cs: &R1CS<C::ScalarField>,
|
r1cs: &R1CS<C::ScalarField>,
|
||||||
@@ -151,7 +160,7 @@ impl<C: CurveGroup> NIFS<C> {
|
|||||||
|
|
||||||
// compute cross terms
|
// compute cross terms
|
||||||
let T = Self::comp_T(&r1cs, phi1.u, phi2.u, &fw1.W, &fw2.W);
|
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);
|
let cmT = Pedersen::commit(&pedersen_params, &T, &rT);
|
||||||
|
|
||||||
// fold witness
|
// fold witness
|
||||||
@@ -193,7 +202,7 @@ impl<C: CurveGroup> NIFS<C> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_commitments(
|
pub fn open_commitments(
|
||||||
tr: &mut Transcript<C::ScalarField>,
|
tr: &mut Transcript<C::ScalarField, C>,
|
||||||
pedersen_params: &PedersenParams<C>,
|
pedersen_params: &PedersenParams<C>,
|
||||||
fw: &FWit<C>,
|
fw: &FWit<C>,
|
||||||
phi: &Phi<C>,
|
phi: &Phi<C>,
|
||||||
@@ -207,7 +216,7 @@ impl<C: CurveGroup> NIFS<C> {
|
|||||||
(cmE_proof, cmW_proof, cmT_proof)
|
(cmE_proof, cmW_proof, cmT_proof)
|
||||||
}
|
}
|
||||||
pub fn verify_commitments(
|
pub fn verify_commitments(
|
||||||
tr: &mut Transcript<C::ScalarField>,
|
tr: &mut Transcript<C::ScalarField, C>,
|
||||||
pedersen_params: &PedersenParams<C>,
|
pedersen_params: &PedersenParams<C>,
|
||||||
phi: Phi<C>,
|
phi: Phi<C>,
|
||||||
cmT: Commitment<C>,
|
cmT: Commitment<C>,
|
||||||
@@ -273,6 +282,7 @@ pub fn gen_test_values<R: Rng, F: PrimeField>(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::pedersen::Pedersen;
|
use crate::pedersen::Pedersen;
|
||||||
|
use crate::transcript::poseidon_test_config;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::CurveGroup;
|
||||||
use ark_mnt4_298::{Fr, G1Projective};
|
use ark_mnt4_298::{Fr, G1Projective};
|
||||||
use ark_std::{
|
use ark_std::{
|
||||||
@@ -287,6 +297,7 @@ mod tests {
|
|||||||
fn test_one_fold() {
|
fn test_one_fold() {
|
||||||
let mut rng = ark_std::test_rng();
|
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 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 (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng);
|
||||||
let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
|
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));
|
assert!(NIFS::<G1Projective>::verify(r, &phi1, &phi2, &phi3, &cmT));
|
||||||
|
|
||||||
// init Prover's transcript
|
// 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
|
// 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
|
// check openings of phi3.cmE, phi3.cmW and cmT
|
||||||
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
||||||
@@ -359,6 +370,7 @@ mod tests {
|
|||||||
fn test_two_fold() {
|
fn test_two_fold() {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 6);
|
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);
|
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);
|
assert_eq!(phi_123_expected.cmW.0, phi_123.cmW.0);
|
||||||
|
|
||||||
// init Prover's transcript
|
// 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
|
// 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
|
// check openings of phi_123.cmE, phi_123.cmW and cmT_123
|
||||||
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
let (cmE_proof, cmW_proof, cmT_proof) = NIFS::<G1Projective>::open_commitments(
|
||||||
@@ -463,6 +475,7 @@ mod tests {
|
|||||||
fn test_nifs_interface() {
|
fn test_nifs_interface() {
|
||||||
let mut rng = ark_std::test_rng();
|
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 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 (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng);
|
||||||
let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
|
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());
|
let fw2 = FWit::<G1Projective>::new(w2.clone(), A.len());
|
||||||
|
|
||||||
// init Prover's transcript
|
// 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
|
// NIFS.P
|
||||||
let (fw3, phi1, phi2, T, cmT) =
|
let (fw3, phi1, phi2, T, cmT) =
|
||||||
NIFS::<G1Projective>::P(&mut transcript_p, &pedersen_params, r, &r1cs, fw1, fw2);
|
NIFS::<G1Projective>::P(&mut transcript_p, &pedersen_params, r, &r1cs, fw1, fw2);
|
||||||
|
|
||||||
// init Verifier's transcript
|
// 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
|
// NIFS.V
|
||||||
let phi3 = NIFS::<G1Projective>::V(r, &phi1, &phi2, &cmT);
|
let phi3 = NIFS::<G1Projective>::V(r, &phi1, &phi2, &cmT);
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
use ark_ec::AffineRepr;
|
use ark_ec::AffineRepr;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::{CurveGroup, Group};
|
||||||
use ark_std::{
|
use ark_std::{
|
||||||
rand::{Rng, RngCore},
|
rand::{Rng, RngCore},
|
||||||
UniformRand,
|
UniformRand,
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::transcript::Transcript;
|
|
||||||
use crate::utils::{naive_msm, vec_add, vector_elem_product};
|
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> {
|
pub struct Proof_elem<C: CurveGroup> {
|
||||||
R: C,
|
R: C,
|
||||||
t1: C::ScalarField,
|
t1: C::ScalarField,
|
||||||
@@ -26,11 +29,19 @@ pub struct Params<C: CurveGroup> {
|
|||||||
pub generators: Vec<C>,
|
pub generators: Vec<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pedersen<C: CurveGroup> {
|
pub struct Pedersen<C: CurveGroup>
|
||||||
_phantom: PhantomData<C>,
|
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> {
|
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();
|
||||||
@@ -63,19 +74,19 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
|
|
||||||
pub fn prove_elem(
|
pub fn prove_elem(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut Transcript<C::ScalarField>,
|
transcript: &mut Transcript<C::ScalarField, C>,
|
||||||
cm: C,
|
cm: C,
|
||||||
v: C::ScalarField,
|
v: C::ScalarField,
|
||||||
r: C::ScalarField,
|
r: C::ScalarField,
|
||||||
) -> Proof_elem<C> {
|
) -> Proof_elem<C> {
|
||||||
let r1 = transcript.get_challenge(b"r_1");
|
let r1 = transcript.get_challenge();
|
||||||
let r2 = transcript.get_challenge(b"r_2");
|
let r2 = transcript.get_challenge();
|
||||||
|
|
||||||
let R: C = (params.g.mul(r1) + params.h.mul(r2));
|
let R: C = (params.g.mul(r1) + params.h.mul(r2));
|
||||||
|
|
||||||
transcript.add(b"cm", &cm);
|
transcript.add_point(&cm);
|
||||||
transcript.add(b"R", &R);
|
transcript.add_point(&R);
|
||||||
let e = transcript.get_challenge(b"e");
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
let t1 = r1 + v * e;
|
let t1 = r1 + v * e;
|
||||||
let t2 = r2 + r * e;
|
let t2 = r2 + r * e;
|
||||||
@@ -84,19 +95,19 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
}
|
}
|
||||||
pub fn prove(
|
pub fn prove(
|
||||||
params: &Params<C>,
|
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
|
cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
|
||||||
v: &Vec<C::ScalarField>,
|
v: &Vec<C::ScalarField>,
|
||||||
r: &C::ScalarField,
|
r: &C::ScalarField,
|
||||||
) -> Proof<C> {
|
) -> Proof<C> {
|
||||||
let r1 = transcript.get_challenge(b"r_1");
|
let r1 = transcript.get_challenge();
|
||||||
let d = transcript.get_challenge_vec(b"d", v.len());
|
let d = transcript.get_challenge_vec(v.len());
|
||||||
|
|
||||||
let R: C = params.h.mul(r1) + naive_msm(&d, ¶ms.generators);
|
let R: C = params.h.mul(r1) + naive_msm(&d, ¶ms.generators);
|
||||||
|
|
||||||
transcript.add(b"cm", &cm.0);
|
transcript.add_point(&cm.0);
|
||||||
transcript.add(b"R", &R);
|
transcript.add_point(&R);
|
||||||
let e = transcript.get_challenge(b"e");
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
let u_ = vec_add(&vector_elem_product(&v, &e), &d);
|
let u_ = vec_add(&vector_elem_product(&v, &e), &d);
|
||||||
let ru_ = e * r + r1;
|
let ru_ = e * r + r1;
|
||||||
@@ -105,17 +116,17 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
}
|
}
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut Transcript<C::ScalarField>,
|
transcript: &mut Transcript<C::ScalarField, C>,
|
||||||
cm: Commitment<C>,
|
cm: Commitment<C>,
|
||||||
proof: Proof<C>,
|
proof: Proof<C>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// r1, d just to match Prover's transcript
|
// r1, d just to match Prover's transcript
|
||||||
transcript.get_challenge(b"r_1");
|
transcript.get_challenge(); // r_1
|
||||||
transcript.get_challenge_vec(b"d", proof.u_.len());
|
transcript.get_challenge_vec(proof.u_.len()); // d
|
||||||
|
|
||||||
transcript.add(b"cm", &cm.0);
|
transcript.add_point(&cm.0);
|
||||||
transcript.add(b"R", &proof.R);
|
transcript.add_point(&proof.R);
|
||||||
let e = transcript.get_challenge(b"e");
|
let e = transcript.get_challenge();
|
||||||
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.generators);
|
let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, ¶ms.generators);
|
||||||
if lhs != rhs {
|
if lhs != rhs {
|
||||||
@@ -126,17 +137,17 @@ impl<C: CurveGroup> Pedersen<C> {
|
|||||||
|
|
||||||
pub fn verify_elem(
|
pub fn verify_elem(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut Transcript<C::ScalarField>,
|
transcript: &mut Transcript<C::ScalarField, C>,
|
||||||
cm: C,
|
cm: C,
|
||||||
proof: Proof_elem<C>,
|
proof: Proof_elem<C>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// s1, s2 just to match Prover's transcript
|
// s1, s2 just to match Prover's transcript
|
||||||
transcript.get_challenge(b"r_1");
|
transcript.get_challenge(); // r_1
|
||||||
transcript.get_challenge(b"r_2");
|
transcript.get_challenge(); // r_2
|
||||||
|
|
||||||
transcript.add(b"cm", &cm);
|
transcript.add_point(&cm);
|
||||||
transcript.add(b"R", &proof.R);
|
transcript.add_point(&proof.R);
|
||||||
let e = transcript.get_challenge(b"e");
|
let e = transcript.get_challenge();
|
||||||
let lhs = proof.R + cm.mul(e);
|
let lhs = proof.R + cm.mul(e);
|
||||||
let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
|
let rhs = params.g.mul(proof.t1) + params.h.mul(proof.t2);
|
||||||
if lhs != rhs {
|
if lhs != rhs {
|
||||||
@@ -153,11 +164,15 @@ pub struct CommitmentElem<C: CurveGroup> {
|
|||||||
pub cm: C,
|
pub cm: C,
|
||||||
pub r: C::ScalarField,
|
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(
|
pub fn prove(
|
||||||
&self,
|
&self,
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
transcript: &mut Transcript<C::ScalarField>,
|
transcript: &mut Transcript<C::ScalarField, C>,
|
||||||
v: C::ScalarField,
|
v: C::ScalarField,
|
||||||
) -> Proof_elem<C> {
|
) -> Proof_elem<C> {
|
||||||
Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
|
Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r)
|
||||||
@@ -167,6 +182,7 @@ impl<C: CurveGroup> CommitmentElem<C> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::transcript::poseidon_test_config;
|
||||||
use ark_ec::CurveGroup;
|
use ark_ec::CurveGroup;
|
||||||
use ark_mnt4_298::{Fr, G1Projective};
|
use ark_mnt4_298::{Fr, G1Projective};
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
@@ -179,11 +195,12 @@ mod tests {
|
|||||||
let params = Pedersen::<G1Projective>::new_params(
|
let params = Pedersen::<G1Projective>::new_params(
|
||||||
&mut rng, 0, /* 0, as here we don't use commit_vec */
|
&mut rng, 0, /* 0, as here we don't use commit_vec */
|
||||||
);
|
);
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
|
||||||
// init Prover's transcript
|
// 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
|
// 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);
|
let v = Fr::rand(&mut rng);
|
||||||
|
|
||||||
@@ -201,11 +218,12 @@ mod tests {
|
|||||||
const n: usize = 10;
|
const n: usize = 10;
|
||||||
// setup params
|
// setup params
|
||||||
let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
|
let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
|
||||||
// init Prover's transcript
|
// 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
|
// 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 v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
|
||||||
let r: Fr = Fr::rand(&mut rng);
|
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
|
// 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.
|
// 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_ff::{BigInteger, PrimeField};
|
||||||
use ark_poly::{
|
use ark_poly::{
|
||||||
multivariate::{SparsePolynomial, SparseTerm, Term},
|
multivariate::{SparsePolynomial, SparseTerm, Term},
|
||||||
@@ -14,23 +15,30 @@ 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 ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb};
|
||||||
|
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
|
|
||||||
pub struct SumCheck<
|
pub struct SumCheck<
|
||||||
F: PrimeField,
|
F: PrimeField + Absorb,
|
||||||
|
C: CurveGroup,
|
||||||
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
||||||
MV: Polynomial<F> + DenseMVPolynomial<F>,
|
MV: Polynomial<F> + DenseMVPolynomial<F>,
|
||||||
> {
|
> {
|
||||||
_f: PhantomData<F>,
|
_f: PhantomData<F>,
|
||||||
|
_c: PhantomData<C>,
|
||||||
_uv: PhantomData<UV>,
|
_uv: PhantomData<UV>,
|
||||||
_mv: PhantomData<MV>,
|
_mv: PhantomData<MV>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
F: PrimeField,
|
F: PrimeField + Absorb,
|
||||||
|
C: CurveGroup,
|
||||||
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
UV: Polynomial<F> + DenseUVPolynomial<F>,
|
||||||
MV: Polynomial<F> + DenseMVPolynomial<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 {
|
fn partial_evaluate(g: &MV, point: &[Option<F>]) -> UV {
|
||||||
assert!(point.len() >= g.num_vars(), "Invalid evaluation domain");
|
assert!(point.len() >= g.num_vars(), "Invalid evaluation domain");
|
||||||
@@ -121,12 +129,12 @@ impl<
|
|||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove(g: MV) -> (F, Vec<UV>, F)
|
pub fn prove(poseidon_config: &PoseidonConfig<F>, g: MV) -> (F, Vec<UV>, F)
|
||||||
where
|
where
|
||||||
<MV as Polynomial<F>>::Point: From<Vec<F>>,
|
<MV as Polynomial<F>>::Point: From<Vec<F>>,
|
||||||
{
|
{
|
||||||
// init transcript
|
// init transcript
|
||||||
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
let mut transcript = Transcript::<F, C>::new(poseidon_config);
|
||||||
|
|
||||||
let v = g.num_vars();
|
let v = g.num_vars();
|
||||||
|
|
||||||
@@ -137,12 +145,12 @@ impl<
|
|||||||
|
|
||||||
H = H + g.evaluate(&p.into());
|
H = H + g.evaluate(&p.into());
|
||||||
}
|
}
|
||||||
transcript.add(b"H", &H);
|
transcript.add(&H);
|
||||||
|
|
||||||
let mut ss: Vec<UV> = Vec::new();
|
let mut ss: Vec<UV> = Vec::new();
|
||||||
let mut r: Vec<F> = vec![];
|
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");
|
let r_i = transcript.get_challenge();
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
|
|
||||||
let var_slots = v - 1 - i;
|
let var_slots = v - 1 - i;
|
||||||
@@ -153,7 +161,7 @@ impl<
|
|||||||
let point = Self::point(r[..i].to_vec(), 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);
|
transcript.add_vec(s_i.coeffs());
|
||||||
ss.push(s_i);
|
ss.push(s_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,10 +169,10 @@ impl<
|
|||||||
(H, ss, last_g_eval)
|
(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
|
// init transcript
|
||||||
let mut transcript: Transcript<F> = Transcript::<F>::new();
|
let mut transcript = Transcript::<F, C>::new(poseidon_config);
|
||||||
transcript.add(b"H", &proof.0);
|
transcript.add(&proof.0);
|
||||||
|
|
||||||
let (c, ss, last_g_eval) = proof;
|
let (c, ss, last_g_eval) = proof;
|
||||||
|
|
||||||
@@ -175,18 +183,18 @@ impl<
|
|||||||
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");
|
let r_i = transcript.get_challenge();
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
transcript.add(b"s_i", s);
|
transcript.add_vec(s.coeffs());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let r_i = transcript.get_challenge(b"r_i");
|
let r_i = transcript.get_challenge();
|
||||||
r.push(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);
|
transcript.add_vec(s.coeffs());
|
||||||
}
|
}
|
||||||
// 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 {
|
||||||
@@ -200,14 +208,15 @@ impl<
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ark_mnt4_298::Fr; // scalar field
|
use crate::transcript::poseidon_test_config;
|
||||||
|
use ark_mnt4_298::{Fr, G1Projective}; // scalar field
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_new_point() {
|
fn test_new_point() {
|
||||||
let f4 = Fr::from(4_u32);
|
let f4 = Fr::from(4_u32);
|
||||||
let f1 = Fr::from(1);
|
let f1 = Fr::from(1);
|
||||||
let f0 = Fr::from(0);
|
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);
|
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);
|
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);
|
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))]);
|
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)]);
|
assert_eq!(e0.coeffs(), vec![Fr::from(16_u32)]);
|
||||||
@@ -293,13 +302,14 @@ mod tests {
|
|||||||
let p = SparsePolynomial::from_coefficients_slice(3, &terms);
|
let p = SparsePolynomial::from_coefficients_slice(3, &terms);
|
||||||
// println!("p {:?}", p);
|
// 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));
|
assert_eq!(proof.0, Fr::from(12_u32));
|
||||||
// println!("proof {:?}", proof);
|
// println!("proof {:?}", proof);
|
||||||
|
|
||||||
let v = SC::verify(proof);
|
let v = SC::verify(&poseidon_config, proof);
|
||||||
assert!(v);
|
assert!(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,12 +345,13 @@ mod tests {
|
|||||||
let p = rand_poly(3, 3, &mut rng);
|
let p = rand_poly(3, 3, &mut rng);
|
||||||
// println!("p {:?}", p);
|
// 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);
|
||||||
println!("proof.s len {:?}", proof.1.len());
|
// println!("proof.s len {:?}", proof.1.len());
|
||||||
|
|
||||||
let v = SC::verify(proof);
|
let v = SC::verify(&poseidon_config, proof);
|
||||||
assert!(v);
|
assert!(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,125 @@
|
|||||||
|
use ark_ec::{AffineRepr, CurveGroup, Group};
|
||||||
use ark_ff::PrimeField;
|
use ark_ff::PrimeField;
|
||||||
use ark_serialize::CanonicalSerialize;
|
use ark_serialize::CanonicalSerialize;
|
||||||
use merlin::Transcript as MerlinTranscript;
|
|
||||||
use std::marker::PhantomData;
|
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 ,
|
use ark_crypto_primitives::sponge::poseidon::{
|
||||||
// using Merlin transcript (https://merlin.cool).
|
constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
|
||||||
pub struct Transcript<F: PrimeField> {
|
};
|
||||||
phantom: PhantomData<F>,
|
use ark_crypto_primitives::sponge::{
|
||||||
transcript: MerlinTranscript,
|
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 + Absorb, C: CurveGroup> Transcript<F, C>
|
||||||
impl<F: PrimeField> Transcript<F> {
|
where
|
||||||
pub fn new() -> Self {
|
<C as CurveGroup>::BaseField: Absorb,
|
||||||
Self {
|
{
|
||||||
phantom: PhantomData::default(),
|
pub fn new(poseidon_config: &PoseidonConfig<F>) -> Self {
|
||||||
transcript: MerlinTranscript::new(b"transcript"),
|
let mut sponge = PoseidonSponge::<F>::new(&poseidon_config);
|
||||||
|
Transcript {
|
||||||
|
sponge,
|
||||||
|
_c: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add<S: CanonicalSerialize>(&mut self, label: &'static [u8], r: &S) {
|
pub fn add(&mut self, v: &F) {
|
||||||
let mut msg = Vec::new();
|
self.sponge.absorb(&v);
|
||||||
r.serialize_uncompressed(&mut msg).unwrap();
|
|
||||||
self.transcript.append_message(label, &msg);
|
|
||||||
}
|
}
|
||||||
pub fn get_challenge(&mut self, label: &'static [u8]) -> F {
|
pub fn add_vec(&mut self, v: &[F]) {
|
||||||
let mut bytes = [0u8; 64];
|
self.sponge.absorb(&v);
|
||||||
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 get_challenge_vec(&mut self, label: &'static [u8], n: usize) -> Vec<F> {
|
pub fn add_point(&mut self, v: &C) {
|
||||||
let mut c: Vec<F> = vec![F::zero(); n];
|
let v_affine = v.into_affine();
|
||||||
for i in 0..n {
|
let xy = v_affine.xy().unwrap(); // WIP
|
||||||
c[i] = self.get_challenge(label);
|
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
|
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