diff --git a/Cargo.toml b/Cargo.toml index b0fa43e..43e311d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nova-snark" -version = "0.17.0" +version = "0.18.0" authors = ["Srinath Setty "] edition = "2021" description = "Recursive zkSNARKs without trusted setup" diff --git a/src/provider/ipa_pc.rs b/src/provider/ipa_pc.rs index 5cfb0bf..09383e4 100644 --- a/src/provider/ipa_pc.rs +++ b/src/provider/ipa_pc.rs @@ -7,7 +7,7 @@ use crate::{ traits::{ commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait}, evaluation::EvaluationEngineTrait, - AppendToTranscriptTrait, ChallengeTrait, Group, TranscriptEngineTrait, + Group, TranscriptEngineTrait, TranscriptReprTrait, }, Commitment, CommitmentKey, CompressedCommitment, CE, }; @@ -139,6 +139,17 @@ impl InnerProductInstance { } } +impl TranscriptReprTrait for InnerProductInstance { + fn to_transcript_bytes(&self) -> Vec { + // we do not need to include self.b_vec as in our context it is produced from the transcript + [ + self.comm_a_vec.to_transcript_bytes(), + self.c.to_transcript_bytes(), + ] + .concat() + } +} + struct InnerProductWitness { a_vec: Vec, } @@ -167,7 +178,7 @@ where CommitmentKey: CommitmentKeyExtTrait, { fn protocol_name() -> &'static [u8] { - b"inner product argument" + b"IPA" } fn prove( @@ -177,17 +188,17 @@ where W: &InnerProductWitness, transcript: &mut G::TE, ) -> Result { - transcript.absorb_bytes(b"protocol-name", Self::protocol_name()); + transcript.dom_sep(Self::protocol_name()); if U.b_vec.len() != W.a_vec.len() { return Err(NovaError::InvalidInputLength); } - U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript); - >::append_to_transcript(&U.c, b"c", transcript); + // absorb the instance in the transcript + transcript.absorb(b"U", U); // sample a random base for commiting to the inner product - let r = G::Scalar::challenge(b"r", transcript)?; + let r = transcript.squeeze(b"r")?; let ck_c = ck_c.scale(&r); // a closure that executes a step of the recursive inner product argument @@ -230,10 +241,10 @@ where ) .compress(); - L.append_to_transcript(b"L", transcript); - R.append_to_transcript(b"R", transcript); + transcript.absorb(b"L", &L); + transcript.absorb(b"R", &R); - let r = G::Scalar::challenge(b"challenge_r", transcript)?; + let r = transcript.squeeze(b"r")?; let r_inverse = r.invert().unwrap(); // fold the left half and the right half @@ -289,7 +300,7 @@ where U: &InnerProductInstance, transcript: &mut G::TE, ) -> Result<(), NovaError> { - transcript.absorb_bytes(b"protocol-name", Self::protocol_name()); + transcript.dom_sep(Self::protocol_name()); if U.b_vec.len() != n || n != (1 << self.L_vec.len()) || self.L_vec.len() != self.R_vec.len() @@ -298,11 +309,11 @@ where return Err(NovaError::InvalidInputLength); } - U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript); - >::append_to_transcript(&U.c, b"c", transcript); + // absorb the instance in the transcript + transcript.absorb(b"U", U); // sample a random base for commiting to the inner product - let r = G::Scalar::challenge(b"r", transcript)?; + let r = transcript.squeeze(b"r")?; let ck_c = ck_c.scale(&r); let P = U.comm_a_vec + CE::::commit(&ck_c, &[U.c]); @@ -337,9 +348,9 @@ where // compute a vector of public coins using self.L_vec and self.R_vec let r = (0..self.L_vec.len()) .map(|i| { - self.L_vec[i].append_to_transcript(b"L", transcript); - self.R_vec[i].append_to_transcript(b"R", transcript); - G::Scalar::challenge(b"challenge_r", transcript) + transcript.absorb(b"L", &self.L_vec[i]); + transcript.absorb(b"R", &self.R_vec[i]); + transcript.squeeze(b"r") }) .collect::, NovaError>>()?; diff --git a/src/provider/keccak.rs b/src/provider/keccak.rs index c73cbca..2629e7c 100644 --- a/src/provider/keccak.rs +++ b/src/provider/keccak.rs @@ -2,13 +2,13 @@ use crate::traits::PrimeFieldExt; use crate::{ errors::NovaError, - traits::{Group, TranscriptEngineTrait}, + traits::{Group, TranscriptEngineTrait, TranscriptReprTrait}, }; use core::marker::PhantomData; use sha3::{Digest, Keccak256}; -const PERSONA_TAG: &[u8] = b"NovaTranscript"; -const DOM_SEP_TAG: &[u8] = b"NovaRound"; +const PERSONA_TAG: &[u8] = b"NoTR"; +const DOM_SEP_TAG: &[u8] = b"NoDS"; const KECCAK256_STATE_SIZE: usize = 64; const KECCAK256_PREFIX_CHALLENGE_LO: u8 = 0; const KECCAK256_PREFIX_CHALLENGE_HI: u8 = 1; @@ -55,7 +55,7 @@ impl TranscriptEngineTrait for Keccak256Transcript { } } - fn squeeze_scalar(&mut self, label: &'static [u8]) -> Result { + fn squeeze(&mut self, label: &'static [u8]) -> Result { let input = [ DOM_SEP_TAG, self.round.to_le_bytes().as_ref(), @@ -81,8 +81,13 @@ impl TranscriptEngineTrait for Keccak256Transcript { Ok(G::Scalar::from_uniform(&output)) } - fn absorb_bytes(&mut self, label: &'static [u8], bytes: &[u8]) { + fn absorb>(&mut self, label: &'static [u8], o: &T) { self.transcript.extend_from_slice(label); + self.transcript.extend_from_slice(&o.to_transcript_bytes()); + } + + fn dom_sep(&mut self, bytes: &'static [u8]) { + self.transcript.extend_from_slice(DOM_SEP_TAG); self.transcript.extend_from_slice(bytes); } } @@ -91,7 +96,7 @@ impl TranscriptEngineTrait for Keccak256Transcript { mod tests { use crate::{ provider::keccak::Keccak256Transcript, - traits::{AppendToTranscriptTrait, ChallengeTrait, Group, TranscriptEngineTrait}, + traits::{Group, TranscriptEngineTrait}, }; use ff::PrimeField; use sha3::{Digest, Keccak256}; @@ -100,50 +105,34 @@ mod tests { #[test] fn test_keccak_transcript() { - let mut transcript = Keccak256Transcript::new(b"test"); + let mut transcript: Keccak256Transcript = Keccak256Transcript::new(b"test"); // two scalars let s1 = ::Scalar::from(2u64); let s2 = ::Scalar::from(5u64); // add the scalars to the transcript - <::Scalar as AppendToTranscriptTrait>::append_to_transcript( - &s1, - b"s1", - &mut transcript, - ); - <::Scalar as AppendToTranscriptTrait>::append_to_transcript( - &s2, - b"s2", - &mut transcript, - ); + transcript.absorb(b"s1", &s1); + transcript.absorb(b"s2", &s2); // make a challenge - let c1 = - <::Scalar as ChallengeTrait>::challenge(b"challenge_c1", &mut transcript) - .unwrap(); + let c1: ::Scalar = transcript.squeeze(b"c1").unwrap(); assert_eq!( hex::encode(c1.to_repr().as_ref()), - "51648083af5387a04a7aa2aec789ee78fdabe45dc1391d270a38fcb576447c01" + "432d5811c8be3d44d47f52108a8749ae18482efd1a37b830f966456b5d75340c" ); // a scalar let s3 = ::Scalar::from(128u64); // add the scalar to the transcript - <::Scalar as AppendToTranscriptTrait>::append_to_transcript( - &s3, - b"s3", - &mut transcript, - ); + transcript.absorb(b"s3", &s3); // make a challenge - let c2 = - <::Scalar as ChallengeTrait>::challenge(b"challenge_c2", &mut transcript) - .unwrap(); + let c2: ::Scalar = transcript.squeeze(b"c2").unwrap(); assert_eq!( hex::encode(c2.to_repr().as_ref()), - "9773f3349f7308153f6012e72b97fc304e48372bbd28bd122b37a8e46855d50f" + "65f7908d53abcd18f3b1d767456ef9009b91c7566a635e9ca7be26e21d4d7a10" ); } diff --git a/src/provider/pasta.rs b/src/provider/pasta.rs index 8f4d773..bdffdd3 100644 --- a/src/provider/pasta.rs +++ b/src/provider/pasta.rs @@ -1,12 +1,11 @@ //! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar. use crate::{ - errors::NovaError, provider::{ keccak::Keccak256Transcript, pedersen::CommitmentEngine, poseidon::{PoseidonRO, PoseidonROCircuit}, }, - traits::{ChallengeTrait, CompressedGroup, Group, PrimeFieldExt, TranscriptEngineTrait}, + traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait}, }; use digest::{ExtendableOutput, Input}; use ff::PrimeField; @@ -177,9 +176,11 @@ macro_rules! impl_traits { let bytes_arr: [u8; 64] = bytes.try_into().unwrap(); $name::Scalar::from_bytes_wide(&bytes_arr) } + } - fn to_bytes(&self) -> Vec { - self.to_repr().as_ref().to_vec() + impl TranscriptReprTrait for $name_compressed { + fn to_transcript_bytes(&self) -> Vec { + self.repr.to_vec() } } @@ -189,17 +190,19 @@ macro_rules! impl_traits { fn decompress(&self) -> Option<$name::Point> { Some($name_curve::from_bytes(&self.repr).unwrap()) } - - fn as_bytes(&self) -> Vec { - self.repr.to_vec() - } } }; } -impl, F: PrimeField> ChallengeTrait for F { - fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result { - transcript.squeeze_scalar(label) +impl TranscriptReprTrait for pallas::Base { + fn to_transcript_bytes(&self) -> Vec { + self.to_repr().to_vec() + } +} + +impl TranscriptReprTrait for pallas::Scalar { + fn to_transcript_bytes(&self) -> Vec { + self.to_repr().to_vec() } } diff --git a/src/provider/pedersen.rs b/src/provider/pedersen.rs index c2cb381..5813941 100644 --- a/src/provider/pedersen.rs +++ b/src/provider/pedersen.rs @@ -3,8 +3,7 @@ use crate::{ errors::NovaError, traits::{ commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait}, - AbsorbInROTrait, AppendToTranscriptTrait, CompressedGroup, Group, ROTrait, - TranscriptEngineTrait, + AbsorbInROTrait, CompressedGroup, Group, ROTrait, TranscriptReprTrait, }, }; use core::{ @@ -12,7 +11,7 @@ use core::{ marker::PhantomData, ops::{Add, AddAssign, Mul, MulAssign}, }; -use ff::{Field, PrimeField}; +use ff::Field; use rayon::prelude::*; use serde::{Deserialize, Serialize}; @@ -89,17 +88,16 @@ impl Default for Commitment { } } -impl AppendToTranscriptTrait for Commitment { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { +impl TranscriptReprTrait for Commitment { + fn to_transcript_bytes(&self) -> Vec { let (x, y, is_infinity) = self.comm.to_coordinates(); let is_infinity_byte = if is_infinity { 0u8 } else { 1u8 }; - let bytes = [ - x.to_repr().as_ref(), - y.to_repr().as_ref(), - &[is_infinity_byte], + [ + x.to_transcript_bytes(), + y.to_transcript_bytes(), + [is_infinity_byte].to_vec(), ] - .concat(); - transcript.absorb_bytes(label, &bytes); + .concat() } } @@ -116,9 +114,9 @@ impl AbsorbInROTrait for Commitment { } } -impl AppendToTranscriptTrait for CompressedCommitment { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { - transcript.absorb_bytes(label, &self.comm.as_bytes()); +impl TranscriptReprTrait for CompressedCommitment { + fn to_transcript_bytes(&self) -> Vec { + self.comm.to_transcript_bytes() } } diff --git a/src/r1cs.rs b/src/r1cs.rs index 7d06a7d..6655674 100644 --- a/src/r1cs.rs +++ b/src/r1cs.rs @@ -9,7 +9,7 @@ use crate::{ }, traits::{ commitment::{CommitmentEngineTrait, CommitmentKeyTrait}, - AbsorbInROTrait, AppendToTranscriptTrait, Group, ROTrait, + AbsorbInROTrait, Group, ROTrait, TranscriptReprTrait, }, Commitment, CommitmentKey, CE, }; @@ -435,13 +435,9 @@ impl R1CSShape { } } -impl AppendToTranscriptTrait for R1CSShape { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { - <::Scalar as AppendToTranscriptTrait>::append_to_transcript( - &self.get_digest(), - label, - transcript, - ); +impl TranscriptReprTrait for R1CSShape { + fn to_transcript_bytes(&self) -> Vec { + self.get_digest().to_transcript_bytes() } } @@ -485,13 +481,6 @@ impl R1CSInstance { } } -impl AppendToTranscriptTrait for R1CSInstance { - fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut G::TE) { - self.comm_W.append_to_transcript(b"comm_W", transcript); - <[G::Scalar] as AppendToTranscriptTrait>::append_to_transcript(&self.X, b"X", transcript); - } -} - impl AbsorbInROTrait for R1CSInstance { fn absorb_in_ro(&self, ro: &mut G::RO) { self.comm_W.absorb_in_ro(ro); @@ -623,12 +612,15 @@ impl RelaxedR1CSInstance { } } -impl AppendToTranscriptTrait for RelaxedR1CSInstance { - fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut G::TE) { - self.comm_W.append_to_transcript(b"comm_W", transcript); - self.comm_E.append_to_transcript(b"comm_E", transcript); - >::append_to_transcript(&self.u, b"u", transcript); - <[G::Scalar] as AppendToTranscriptTrait>::append_to_transcript(&self.X, b"X", transcript); +impl TranscriptReprTrait for RelaxedR1CSInstance { + fn to_transcript_bytes(&self) -> Vec { + [ + self.comm_W.to_transcript_bytes(), + self.comm_E.to_transcript_bytes(), + self.u.to_transcript_bytes(), + self.X.as_slice().to_transcript_bytes(), + ] + .concat() } } diff --git a/src/spartan/mod.rs b/src/spartan/mod.rs index 8089c36..dc1efcb 100644 --- a/src/spartan/mod.rs +++ b/src/spartan/mod.rs @@ -7,8 +7,7 @@ use crate::{ errors::NovaError, r1cs::{R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness}, traits::{ - evaluation::EvaluationEngineTrait, snark::RelaxedR1CSSNARKTrait, AppendToTranscriptTrait, - ChallengeTrait, Group, TranscriptEngineTrait, + evaluation::EvaluationEngineTrait, snark::RelaxedR1CSSNARKTrait, Group, TranscriptEngineTrait, }, CommitmentKey, }; @@ -83,8 +82,8 @@ impl> RelaxedR1CSSNARKTrait> RelaxedR1CSSNARKTrait, NovaError>>()?; let mut poly_tau = MultilinearPolynomial::new(EqPolynomial::new(tau).evals()); @@ -134,15 +133,13 @@ impl> RelaxedR1CSSNARKTrait>::append_to_transcript( - &[claim_Az, claim_Bz, claim_Cz, eval_E], + transcript.absorb( b"claims_outer", - &mut transcript, + &[claim_Az, claim_Bz, claim_Cz, eval_E].as_slice(), ); // inner sum-check - let r = G::Scalar::challenge(b"r", &mut transcript)?; + let r = transcript.squeeze(b"r")?; let claim_inner_joint = claim_Az + r * claim_Bz + r * r * claim_Cz; let poly_ABC = { @@ -213,11 +210,7 @@ impl> RelaxedR1CSSNARKTrait>::append_to_transcript( - &eval_W, - b"eval_W", - &mut transcript, - ); + transcript.absorb(b"eval_W", &eval_W); // We will now reduce eval_W =? W(r_y[1..]) and eval_W =? E(r_x) into // two claims: eval_W_prime =? W(rz) and eval_E_prime =? E(rz) @@ -225,7 +218,7 @@ impl> RelaxedR1CSSNARKTrait> RelaxedR1CSSNARKTrait>::append_to_transcript( - &[eval_E_prime, eval_W_prime], - b"claims_batch", - &mut transcript, - ); + transcript.absorb(b"claims_batch", &[eval_E_prime, eval_W_prime].as_slice()); // we now combine evaluation claims at the same point rz into one - let gamma = G::Scalar::challenge(b"gamma", &mut transcript)?; + let gamma = transcript.squeeze(b"gamma")?; let comm = U.comm_E + U.comm_W * gamma; let poly = W .E @@ -285,8 +274,8 @@ impl> RelaxedR1CSSNARKTrait> RelaxedR1CSSNARKTrait, NovaError>>()?; let (claim_outer_final, r_x) = @@ -312,19 +301,19 @@ impl> RelaxedR1CSSNARKTrait>::append_to_transcript( + transcript.absorb( + b"claims_outer", &[ self.claims_outer.0, self.claims_outer.1, self.claims_outer.2, self.eval_E, - ], - b"claims_outer", - &mut transcript, + ] + .as_slice(), ); // inner sum-check - let r = G::Scalar::challenge(b"r", &mut transcript)?; + let r = transcript.squeeze(b"r")?; let claim_inner_joint = self.claims_outer.0 + r * self.claims_outer.1 + r * r * self.claims_outer.2; @@ -380,13 +369,9 @@ impl> RelaxedR1CSSNARKTrait>::append_to_transcript( - &self.eval_W, - b"eval_W", - &mut transcript, - ); + transcript.absorb(b"eval_W", &self.eval_W); - let rho = G::Scalar::challenge(b"rho", &mut transcript)?; + let rho = transcript.squeeze(b"rho")?; let claim_batch_joint = self.eval_E + rho * self.eval_W; let num_rounds_z = num_rounds_x; let (claim_batch_final, r_z) = @@ -405,14 +390,13 @@ impl> RelaxedR1CSSNARKTrait>::append_to_transcript( - &[self.eval_E_prime, self.eval_W_prime], + transcript.absorb( b"claims_batch", - &mut transcript, + &[self.eval_E_prime, self.eval_W_prime].as_slice(), ); // we now combine evaluation claims at the same point rz into one - let gamma = G::Scalar::challenge(b"gamma", &mut transcript)?; + let gamma = transcript.squeeze(b"gamma")?; let comm = U.comm_E + U.comm_W * gamma; let eval = self.eval_E_prime + gamma * self.eval_W_prime; diff --git a/src/spartan/sumcheck.rs b/src/spartan/sumcheck.rs index eea2b6e..f73ae05 100644 --- a/src/spartan/sumcheck.rs +++ b/src/spartan/sumcheck.rs @@ -2,7 +2,7 @@ #![allow(clippy::type_complexity)] use super::polynomial::MultilinearPolynomial; use crate::errors::NovaError; -use crate::traits::{AppendToTranscriptTrait, ChallengeTrait, Group}; +use crate::traits::{Group, TranscriptEngineTrait, TranscriptReprTrait}; use core::marker::PhantomData; use ff::Field; use rayon::prelude::*; @@ -43,10 +43,10 @@ impl SumcheckProof { debug_assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e); // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); + transcript.absorb(b"p", &poly); //derive the verifier's challenge for the next round - let r_i = G::Scalar::challenge(b"challenge", transcript)?; + let r_i = transcript.squeeze(b"c")?; r.push(r_i); @@ -98,10 +98,10 @@ impl SumcheckProof { }; // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); + transcript.absorb(b"p", &poly); //derive the verifier's challenge for the next round - let r_i = G::Scalar::challenge(b"challenge", transcript)?; + let r_i = transcript.squeeze(b"c")?; r.push(r_i); polys.push(poly.compress()); @@ -172,10 +172,10 @@ impl SumcheckProof { }; // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); + transcript.absorb(b"p", &poly); - //derive the verifier's challenge for the next round - let r_i = G::Scalar::challenge(b"challenge", transcript)?; + // derive the verifier's challenge for the next round + let r_i = transcript.squeeze(b"c")?; r.push(r_i); polys.push(poly.compress()); @@ -266,10 +266,10 @@ impl SumcheckProof { }; // append the prover's message to the transcript - poly.append_to_transcript(b"poly", transcript); + transcript.absorb(b"p", &poly); //derive the verifier's challenge for the next round - let r_i = G::Scalar::challenge(b"challenge", transcript)?; + let r_i = transcript.squeeze(b"c")?; r.push(r_i); polys.push(poly.compress()); @@ -396,12 +396,9 @@ impl CompressedUniPoly { } } -impl AppendToTranscriptTrait for UniPoly { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { - <[G::Scalar] as AppendToTranscriptTrait>::append_to_transcript( - &self.coeffs, - label, - transcript, - ); +impl TranscriptReprTrait for UniPoly { + fn to_transcript_bytes(&self) -> Vec { + let coeffs = self.compress().coeffs_except_linear_term; + coeffs.as_slice().to_transcript_bytes() } } diff --git a/src/traits/commitment.rs b/src/traits/commitment.rs index e105704..a1e2b96 100644 --- a/src/traits/commitment.rs +++ b/src/traits/commitment.rs @@ -2,7 +2,7 @@ //! We require the commitment engine to provide a commitment to vectors with a single group element use crate::{ errors::NovaError, - traits::{AbsorbInROTrait, AppendToTranscriptTrait, Group}, + traits::{AbsorbInROTrait, Group, TranscriptReprTrait}, }; use core::{ fmt::Debug, @@ -65,10 +65,10 @@ pub trait CommitmentTrait: + Eq + Send + Sync + + TranscriptReprTrait + Serialize + for<'de> Deserialize<'de> + AbsorbInROTrait - + AppendToTranscriptTrait + CommitmentOps + CommitmentOpsOwned + ScalarMul @@ -80,9 +80,9 @@ pub trait CommitmentTrait: + Eq + Send + Sync + + TranscriptReprTrait + Serialize - + for<'de> Deserialize<'de> - + AppendToTranscriptTrait; + + for<'de> Deserialize<'de>; /// Compresses self into a compressed commitment fn compress(&self) -> Self::CompressedCommitment; diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 78f6f60..4618402 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -34,15 +34,19 @@ pub trait Group: + for<'de> Deserialize<'de> { /// A type representing an element of the base field of the group - type Base: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>; + type Base: PrimeField + + PrimeFieldBits + + TranscriptReprTrait + + Serialize + + for<'de> Deserialize<'de>; /// A type representing an element of the scalar field of the group type Scalar: PrimeField + PrimeFieldBits + PrimeFieldExt - + ChallengeTrait + Send + Sync + + TranscriptReprTrait + Serialize + for<'de> Deserialize<'de>; @@ -97,16 +101,23 @@ pub trait Group: /// Represents a compressed version of a group element pub trait CompressedGroup: - Clone + Copy + Debug + Eq + Sized + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static + Clone + + Copy + + Debug + + Eq + + Sized + + Send + + Sync + + TranscriptReprTrait + + Serialize + + for<'de> Deserialize<'de> + + 'static { /// A type that holds the decompressed version of the compressed group element type GroupElement: Group + Serialize + for<'de> Deserialize<'de>; /// Decompresses the compressed group element fn decompress(&self) -> Option; - - /// Returns a byte array representing the compressed group element - fn as_bytes(&self) -> Vec; } /// A helper trait to absorb different objects in RO @@ -196,56 +207,43 @@ impl ScalarMul for T where T: Mul: for<'r> ScalarMul<&'r Rhs, Output> {} impl ScalarMulOwned for T where T: for<'r> ScalarMul<&'r Rhs, Output> {} +/// This trait allows types to implement how they want to be added to TranscriptEngine +pub trait TranscriptReprTrait: Send + Sync { + /// returns a byte representation of self to be added to the transcript + fn to_transcript_bytes(&self) -> Vec; +} + /// This trait defines the behavior of a transcript engine compatible with Spartan pub trait TranscriptEngineTrait: Send + Sync { /// initializes the transcript fn new(label: &'static [u8]) -> Self; /// returns a scalar element of the group as a challenge - fn squeeze_scalar(&mut self, label: &'static [u8]) -> Result; + fn squeeze(&mut self, label: &'static [u8]) -> Result; - /// absorbs a label and a sequence of bytes - fn absorb_bytes(&mut self, label: &'static [u8], bytes: &[u8]); -} - -/// A helper trait to append different types to the transcript -pub trait AppendToTranscriptTrait { - /// appends the value to the transcript under the provided label - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE); -} + /// absorbs any type that implements TranscriptReprTrait under a label + fn absorb>(&mut self, label: &'static [u8], o: &T); -/// A helper trait to generate challenges using a transcript object -pub trait ChallengeTrait { - /// Returns a challenge from the transcript - fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result - where - Self: Sized; + /// adds a domain separator + fn dom_sep(&mut self, bytes: &'static [u8]); } /// Defines additional methods on PrimeField objects pub trait PrimeFieldExt: PrimeField { /// Returns a scalar representing the bytes fn from_uniform(bytes: &[u8]) -> Self; - - /// Returns a vector of bytes representing the scalar - fn to_bytes(&self) -> Vec; -} - -impl, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait for F { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { - transcript.absorb_bytes(label, &::to_bytes(self)); - } } -impl, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait for [F] { - fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) { - let bytes = (0..self.len()) - .map(|i| ::to_bytes(&self[i])) +impl, F: PrimeField + TranscriptReprTrait> TranscriptReprTrait + for &[F] +{ + fn to_transcript_bytes(&self) -> Vec { + (0..self.len()) + .map(|i| >::to_transcript_bytes(&self[i])) .collect::>() .into_iter() .flatten() - .collect::>(); - transcript.absorb_bytes(label, &bytes); + .collect::>() } }