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:
2023-04-29 14:15:25 +02:00
parent eb289313b0
commit 7cf729f00a
6 changed files with 234 additions and 104 deletions

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -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, &params.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_, &params.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);

View File

@@ -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);
}
}

View File

@@ -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());
// }
// }