diff --git a/src/transcript.rs b/src/transcript.rs index 2bc5042a..0d98a2e1 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -12,10 +12,25 @@ use std::io::{self, Read, Write}; use std::marker::PhantomData; /// Generic transcript view (from either the prover or verifier's perspective) -pub trait Transcript { +pub trait Transcript> { /// Squeeze a challenge (in the base field) from the transcript. fn squeeze_challenge(&mut self) -> C::Base; + /// Squeeze a 128-bit verifier challenge from the transcript. + fn squeeze_challenge_128(&mut self) -> Challenge { + Challenge(self.squeeze_challenge().get_lower_128()) + } + + /// Get a scalar challenge from a 128-bit challenge. + fn to_challenge_scalar(&self, challenge: Challenge) -> ChallengeScalar { + S::to_challenge_scalar::(challenge) + } + + /// Squeeze a scalar challenge from the transcript. + fn squeeze_challenge_scalar(&mut self) -> ChallengeScalar { + S::to_challenge_scalar::(self.squeeze_challenge_128()) + } + /// Writing the point to the transcript without writing it to the proof, /// treating it as a common input. fn common_point(&mut self, point: C) -> io::Result<()>; @@ -27,7 +42,7 @@ pub trait Transcript { /// Transcript view from the perspective of a verifier that has access to an /// input stream of data from the prover to the verifier. -pub trait TranscriptRead: Transcript { +pub trait TranscriptRead>: Transcript { /// Read a curve point from the prover. fn read_point(&mut self) -> io::Result; @@ -37,7 +52,7 @@ pub trait TranscriptRead: Transcript { /// Transcript view from the perspective of a prover that has access to an /// output stream of messages from the prover to the verifier. -pub trait TranscriptWrite: Transcript { +pub trait TranscriptWrite>: Transcript { /// Write a curve point to the proof and the transcript. fn write_point(&mut self, point: C) -> io::Result<()>; @@ -47,13 +62,14 @@ pub trait TranscriptWrite: Transcript { /// We will replace BLAKE2b with an algebraic hash function in a later version. #[derive(Debug, Clone)] -pub struct Blake2bRead { +pub struct Blake2bRead> { state: Blake2bState, reader: R, _marker: PhantomData, + _marker_s: PhantomData, } -impl Blake2bRead { +impl> Blake2bRead { /// Initialize a transcript given an input buffer and a key. pub fn init(reader: R) -> Self { Blake2bRead { @@ -63,11 +79,12 @@ impl Blake2bRead { .to_state(), reader, _marker: PhantomData, + _marker_s: PhantomData, } } } -impl TranscriptRead for Blake2bRead { +impl> TranscriptRead for Blake2bRead { fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); self.reader.read_exact(compressed.as_mut())?; @@ -94,7 +111,7 @@ impl TranscriptRead for Blake2bRead { } } -impl Transcript for Blake2bRead { +impl> Transcript for Blake2bRead { fn common_point(&mut self, point: C) -> io::Result<()> { let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { io::Error::new( @@ -124,13 +141,14 @@ impl Transcript for Blake2bRead { /// We will replace BLAKE2b with an algebraic hash function in a later version. #[derive(Debug, Clone)] -pub struct Blake2bWrite { +pub struct Blake2bWrite> { state: Blake2bState, writer: W, _marker: PhantomData, + _marker_s: PhantomData, } -impl Blake2bWrite { +impl> Blake2bWrite { /// Initialize a transcript given an output buffer and a key. pub fn init(writer: W) -> Self { Blake2bWrite { @@ -140,6 +158,7 @@ impl Blake2bWrite { .to_state(), writer, _marker: PhantomData, + _marker_s: PhantomData, } } @@ -150,7 +169,9 @@ impl Blake2bWrite { } } -impl TranscriptWrite for Blake2bWrite { +impl> TranscriptWrite + for Blake2bWrite +{ fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; let compressed = point.to_bytes(); @@ -163,7 +184,7 @@ impl TranscriptWrite for Blake2bWrite { } } -impl Transcript for Blake2bWrite { +impl> Transcript for Blake2bWrite { fn common_point(&mut self, point: C) -> io::Result<()> { let coords: Coordinates = Option::from(point.coordinates()).ok_or_else(|| { io::Error::new( @@ -195,27 +216,34 @@ impl Transcript for Blake2bWrite { #[derive(Copy, Clone, Debug)] pub struct Challenge(pub(crate) u128); -impl Challenge { - /// Obtains a new challenge from the transcript. - pub fn get>(transcript: &mut T) -> Challenge { - Challenge(transcript.squeeze_challenge().get_lower_128()) - } -} - /// The scalar representation of a verifier challenge. /// /// The `Type` type can be used to scope the challenge to a specific context, or -/// set to `()` if no context is required. +/// set to `Default` if no context is required. #[derive(Copy, Clone, Debug)] -pub struct ChallengeScalar { +pub struct ChallengeScalar { inner: C::Scalar, - _marker: PhantomData, + _marker: PhantomData, } -impl From for ChallengeScalar { - /// This algorithm applies the mapping of Algorithm 1 from the - /// [Halo](https://eprint.iacr.org/2019/1021) paper. - fn from(challenge: Challenge) -> Self { +/// The challenge space used to sample a scalar from a 128-bit challenge. +/// This protocol supports implementations for `ChallengeScalarEndo`, which +/// uses an endomorphism, and `ChallengeScalarFull`, which samples the +/// full-width field. +pub trait ChallengeSpace { + /// Derive a scalar from a 128-bit challenge in a certain challenge space. + fn to_challenge_scalar(challenge: Challenge) -> ChallengeScalar; +} + +/// The scalar challenge space that applies the mapping of Algorithm 1 from the +/// [Halo](https://eprint.iacr.org/2019/1021) paper. +#[derive(Debug)] +pub struct ChallengeScalarEndo { + _marker: PhantomData, +} + +impl ChallengeSpace for ChallengeScalarEndo { + fn to_challenge_scalar(challenge: Challenge) -> ChallengeScalar { let mut acc = (C::Scalar::ZETA + &C::Scalar::one()).double(); for i in (0..64).rev() { @@ -238,17 +266,24 @@ impl From for ChallengeScalar { } } -impl ChallengeScalar { - /// Obtains a new challenge from the transcript. - pub fn get>(transcript: &mut T) -> Self - where - C: CurveAffine, - { - Challenge::get(transcript).into() +/// The scalar challenge space that samples from the full-width field. +#[derive(Debug)] +pub struct ChallengeScalarFull { + _marker: PhantomData, +} + +impl ChallengeSpace for ChallengeScalarFull { + /// This algorithm applies the mapping of Algorithm 1 from the + /// [Halo](https://eprint.iacr.org/2019/1021) paper. + fn to_challenge_scalar(challenge: Challenge) -> ChallengeScalar { + ChallengeScalar { + inner: C::Scalar::from_u128(challenge.0), + _marker: PhantomData, + } } } -impl Deref for ChallengeScalar { +impl Deref for ChallengeScalar { type Target = C::Scalar; fn deref(&self) -> &C::Scalar { @@ -256,14 +291,14 @@ impl Deref for ChallengeScalar { } } -pub(crate) fn read_n_points>( +pub(crate) fn read_n_points, T: TranscriptRead>( transcript: &mut T, n: usize, ) -> io::Result> { (0..n).map(|_| transcript.read_point()).collect() } -pub(crate) fn read_n_scalars>( +pub(crate) fn read_n_scalars, T: TranscriptRead>( transcript: &mut T, n: usize, ) -> io::Result> {