Make code generic over a TranscriptEngine (#139)

This commit is contained in:
Srinath Setty
2023-02-09 18:33:48 -08:00
committed by GitHub
parent b97786d291
commit 8faffd38ea
13 changed files with 400 additions and 153 deletions

View File

@@ -71,7 +71,7 @@ pub trait CommitmentTrait<G: Group>:
+ Serialize
+ for<'de> Deserialize<'de>
+ AbsorbInROTrait<G>
+ AppendToTranscriptTrait
+ AppendToTranscriptTrait<G>
+ CommitmentOps
+ CommitmentOpsOwned
+ ScalarMul<G::Scalar>
@@ -96,7 +96,7 @@ pub trait CompressedCommitmentTrait<C: CompressedGroup>:
+ Sync
+ Serialize
+ for<'de> Deserialize<'de>
+ AppendToTranscriptTrait
+ AppendToTranscriptTrait<C::GroupElement>
{
/// Holds the type of the commitment that can be decompressed into
type Commitment;

View File

@@ -5,7 +5,6 @@ use crate::{
errors::NovaError,
traits::{commitment::CommitmentEngineTrait, Group},
};
use merlin::Transcript;
use serde::{Deserialize, Serialize};
/// A trait that ties different pieces of the commitment evaluation together
@@ -27,7 +26,7 @@ pub trait EvaluationEngineTrait<G: Group>:
/// A method to prove evaluations of a batch of polynomials
fn prove_batch(
gens: &Self::EvaluationGens,
transcript: &mut Transcript,
transcript: &mut G::TE,
comm: &[<Self::CE as CommitmentEngineTrait<G>>::Commitment],
polys: &[Vec<G::Scalar>],
points: &[Vec<G::Scalar>],
@@ -37,7 +36,7 @@ pub trait EvaluationEngineTrait<G: Group>:
/// A method to verify purported evaluations of a batch of polynomials
fn verify_batch(
gens: &Self::EvaluationGens,
transcript: &mut Transcript,
transcript: &mut G::TE,
comm: &[<Self::CE as CommitmentEngineTrait<G>>::Commitment],
points: &[Vec<G::Scalar>],
evals: &[G::Scalar],

View File

@@ -1,4 +1,5 @@
//! This module defines various traits required by the users of the library to implement.
use crate::errors::NovaError;
use bellperson::{
gadgets::{boolean::AllocatedBit, num::AllocatedNum},
ConstraintSystem, SynthesisError,
@@ -8,7 +9,6 @@ use core::{
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
};
use ff::{PrimeField, PrimeFieldBits};
use merlin::Transcript;
use num_bigint::BigInt;
use serde::{Deserialize, Serialize};
@@ -39,7 +39,8 @@ pub trait Group:
/// A type representing an element of the scalar field of the group
type Scalar: PrimeField
+ PrimeFieldBits
+ ChallengeTrait
+ PrimeFieldExt
+ ChallengeTrait<Self>
+ Send
+ Sync
+ Serialize
@@ -53,13 +54,16 @@ pub trait Group:
/// A type representing preprocessed group element
type PreprocessedGroupElement: Clone + Debug + Send + Sync + Serialize + for<'de> Deserialize<'de>;
/// A type that represents a hash function that consumes elements
/// A type that represents a circuit-friendly sponge that consumes elements
/// from the base field and squeezes out elements of the scalar field
type RO: ROTrait<Self::Base, Self::Scalar> + Serialize + for<'de> Deserialize<'de>;
/// An alternate implementation of Self::RO in the circuit model
type ROCircuit: ROCircuitTrait<Self::Base> + Serialize + for<'de> Deserialize<'de>;
/// A type that provides a generic Fiat-Shamir transcript to be used when externalizing proofs
type TE: TranscriptEngineTrait<Self>;
/// A type that defines a commitment engine over scalars in the group
type CE: CommitmentEngineTrait<Self> + Serialize + for<'de> Deserialize<'de>;
@@ -105,24 +109,12 @@ pub trait CompressedGroup:
fn as_bytes(&self) -> &[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 Transcript);
}
/// A helper trait to absorb different objects in RO
pub trait AbsorbInROTrait<G: Group> {
/// Absorbs the value in the provided RO
fn absorb_in_ro(&self, ro: &mut G::RO);
}
/// A helper trait to generate challenges using a transcript object
pub trait ChallengeTrait {
/// Returns a Scalar representing the challenge using the transcript
fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self;
}
/// A helper trait that defines the behavior of a hash function that we use as an RO
pub trait ROTrait<Base, Scalar> {
/// A type representing constants/parameters associated with the hash function
@@ -204,17 +196,63 @@ impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Out
pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
impl<F: PrimeField> AppendToTranscriptTrait for F {
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
transcript.append_message(label, self.to_repr().as_ref());
/// This trait defines the behavior of a transcript engine compatible with Spartan
pub trait TranscriptEngineTrait<G: Group>: 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<G::Scalar, NovaError>;
/// 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<G: Group> {
/// appends the value to the transcript under the provided label
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE);
}
/// A helper trait to generate challenges using a transcript object
pub trait ChallengeTrait<G: Group> {
/// Returns a challenge from the transcript
fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result<Self, NovaError>
where
Self: Sized;
}
/// Defines additional methods on PrimeField objects
pub trait PrimeFieldExt: PrimeField {
/// Returns a Scalar representing the bytes
fn from_uniform(bytes: &[u8]) -> Self;
/// Returns a byte representation
fn to_bytes(v: &[Self]) -> Vec<u8> {
(0..v.len())
.map(|i| v[i].to_repr().as_ref().to_vec())
.collect::<Vec<Vec<u8>>>()
.into_iter()
.flatten()
.collect::<Vec<u8>>()
}
}
impl<F: PrimeField> AppendToTranscriptTrait for [F] {
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
for s in self {
s.append_to_transcript(label, transcript);
}
impl<G: Group<Scalar = F>, F: PrimeField> ChallengeTrait<G> for F {
fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result<F, NovaError> {
transcript.squeeze_scalar(label)
}
}
impl<G: Group<Scalar = F>, F: PrimeField> AppendToTranscriptTrait<G> for F {
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
transcript.absorb_bytes(label, self.to_repr().as_ref());
}
}
impl<G: Group<Scalar = F>, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait<G> for [F] {
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
transcript.absorb_bytes(label, &<F as PrimeFieldExt>::to_bytes(self));
}
}