From d726f046bc22ec960a378228f97887f2d9fc5e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Tue, 30 Jan 2024 11:17:34 +0100 Subject: [PATCH] Simpler Arthur API to work with algebraic hashes. --- examples/schnorr_algebraic_hash.rs | 16 ++++++------- src/arthur.rs | 37 ++++++++++++++++++++++-------- src/iopattern.rs | 2 +- src/plugins/ark/common.rs | 8 +++---- src/plugins/ark/writer.rs | 12 +++++----- src/plugins/group/writer.rs | 6 ++--- 6 files changed, 49 insertions(+), 32 deletions(-) diff --git a/examples/schnorr_algebraic_hash.rs b/examples/schnorr_algebraic_hash.rs index 1c45660..e9052b2 100644 --- a/examples/schnorr_algebraic_hash.rs +++ b/examples/schnorr_algebraic_hash.rs @@ -1,12 +1,11 @@ /// This code is pretty much the same as the one in `schnorr.rs`, -/// except that +/// except for minor changes in order to work with algebraic hashes +/// over the scalar field of BLS12-381. use ark_ec::{CurveGroup, PrimeGroup}; use ark_ff::PrimeField; use ark_std::UniformRand; use nimue::plugins::ark::*; -use rand::{rngs::OsRng, CryptoRng, RngCore}; - /// Extend the IO pattern with the Schnorr protocol. trait SchnorrIOPattern { /// Adds the entire Schnorr protocol to the IO pattern (statement and proof). @@ -34,7 +33,7 @@ where /// a secret key `sk` in $\mathbb{Z}_p$ /// and its respective public key `pk` in $\mathbb{G}$. fn keygen() -> (G::ScalarField, G) { - let sk = G::ScalarField::rand(&mut OsRng); + let sk = G::ScalarField::rand(&mut nimue::DefaultRng::default()); let pk = G::generator() * sk; (sk, pk) } @@ -45,10 +44,10 @@ fn keygen() -> (G::ScalarField, G) { /// - the secret key $x \in \mathbb{Z}_p$ /// It returns a zero-knowledge proof of knowledge of `x` as a sequence of bytes. #[allow(non_snake_case)] -fn prove( +fn prove( // the hash function `H` works over bytes. // Algebraic hashes over a particular domain can be denoted with an additional type argument implementing `nimue::Unit`. - arthur: &mut Arthur, + arthur: &mut Arthur, // the generator P: G, // the secret key @@ -57,10 +56,9 @@ fn prove( where U: Unit, G::BaseField: PrimeField, - R: CryptoRng + RngCore, H: DuplexHash, G: CurveGroup, - Arthur: GroupWriter + FieldWriter + ByteChallenges, + Arthur: GroupWriter + FieldWriter + ByteChallenges, { // `Arthur` types implement a cryptographically-secure random number generator that is tied to the protocol transcript // and that can be accessed via the `rng()` funciton. @@ -152,7 +150,7 @@ fn main() { let (x, X) = keygen(); // Create the prover transcript, add the statement to it, and then invoke the prover. - let mut arthur = Arthur::::new(&io, OsRng); + let mut arthur = io.to_arthur(); arthur.public_points(&[P, X]).unwrap(); arthur.ratchet().unwrap(); let proof = prove(&mut arthur, P, x).expect("Invalid proof"); diff --git a/src/arthur.rs b/src/arthur.rs index 38126e8..73713d5 100644 --- a/src/arthur.rs +++ b/src/arthur.rs @@ -8,7 +8,7 @@ use super::{DefaultHash, DefaultRng, IOPatternError}; /// A cryptographically-secure random number generator that is bound to the protocol transcript. /// -/// For most public-coin protocols it is *vital* not to have two commitments for the same challenge. +/// For most public-coin protocols it is *vital* not to have two different verifier messages for the same prover message. /// For this reason, we construct a Rng that will absorb whatever the verifier absorbs, and that in addition /// it is seeded by a cryptographic random number generator (by default, [`rand::rngs::OsRng`]). /// @@ -50,7 +50,7 @@ impl RngCore for ProverRng { } } -impl Arthur +impl Arthur where H: DuplexHash, R: RngCore + CryptoRng, @@ -71,7 +71,7 @@ where } } -impl From for Arthur +impl From for Arthur where U: Unit, H: DuplexHash, @@ -84,11 +84,11 @@ where /// The state of an interactive proof system. /// Holds the state of the verifier, and provides the random coins for the prover. -pub struct Arthur +pub struct Arthur where + U: Unit, H: DuplexHash, R: RngCore + CryptoRng, - U: Unit, { /// The randomness state of the prover. pub(crate) rng: ProverRng, @@ -98,7 +98,12 @@ where pub(crate) transcript: Vec, } -impl> Arthur { +impl Arthur +where + U: Unit, + H: DuplexHash, + R: RngCore + CryptoRng, +{ #[inline(always)] pub fn add(&mut self, input: &[U]) -> Result<(), IOPatternError> { // let serialized = bincode::serialize(input).unwrap(); @@ -129,7 +134,12 @@ impl> Arthur { } } -impl, R: RngCore + CryptoRng, U: Unit> UnitTranscript for Arthur { +impl UnitTranscript for Arthur +where + U: Unit, + H: DuplexHash, + R: RngCore + CryptoRng, +{ fn public_units(&mut self, input: &[U]) -> Result<(), IOPatternError> { let len = self.transcript.len(); self.add(input)?; @@ -144,13 +154,22 @@ impl, R: RngCore + CryptoRng, U: Unit> UnitTranscript for Ar impl CryptoRng for ProverRng {} -impl> core::fmt::Debug for Arthur { +impl core::fmt::Debug for Arthur +where + U: Unit, + H: DuplexHash, + R: RngCore + CryptoRng, +{ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.safe.fmt(f) } } -impl ByteWriter for Arthur { +impl ByteWriter for Arthur +where + H: DuplexHash, + R: RngCore + CryptoRng, +{ #[inline(always)] fn add_bytes(&mut self, input: &[u8]) -> Result<(), IOPatternError> { self.add(input) diff --git a/src/iopattern.rs b/src/iopattern.rs index 7a168c9..00d8c0c 100644 --- a/src/iopattern.rs +++ b/src/iopattern.rs @@ -173,7 +173,7 @@ impl, U: Unit> IOPattern { } } - pub fn to_arthur(&self) -> crate::Arthur { + pub fn to_arthur(&self) -> crate::Arthur { crate::Arthur::new(self, crate::DefaultRng::default()) } diff --git a/src/plugins/ark/common.rs b/src/plugins/ark/common.rs index 5c53778..0f4f3ae 100644 --- a/src/plugins/ark/common.rs +++ b/src/plugins/ark/common.rs @@ -93,7 +93,7 @@ where // Field <-> Field interactions: -impl FieldPublic> for Arthur> +impl FieldPublic> for Arthur, R> where H: DuplexHash>, R: RngCore + CryptoRng, @@ -139,7 +139,7 @@ where } } -impl GroupPublic for Arthur> +impl GroupPublic for Arthur, R> where C: FpConfig, R: RngCore + CryptoRng, @@ -189,7 +189,7 @@ where } } -impl<'a, H, R, C, const N: usize> BytePublic for Arthur> +impl<'a, H, R, C, const N: usize> BytePublic for Arthur, R> where C: FpConfig, H: DuplexHash>, @@ -203,7 +203,7 @@ where } } -impl<'a, H, R, C, const N: usize> ByteChallenges for Arthur> +impl<'a, H, R, C, const N: usize> ByteChallenges for Arthur, R> where C: FpConfig, H: DuplexHash>, diff --git a/src/plugins/ark/writer.rs b/src/plugins/ark/writer.rs index ba51eb6..07fb3a7 100644 --- a/src/plugins/ark/writer.rs +++ b/src/plugins/ark/writer.rs @@ -6,7 +6,7 @@ use rand::{CryptoRng, RngCore}; use super::{FieldPublic, FieldWriter, GroupPublic, GroupWriter}; use crate::{Arthur, DuplexHash, ProofResult, UnitTranscript}; -impl FieldWriter for Arthur { +impl FieldWriter for Arthur { fn add_scalars(&mut self, input: &[F]) -> ProofResult<()> { let serialized = self.public_scalars(input); self.transcript.extend(serialized?); @@ -15,7 +15,7 @@ impl FieldWriter for Ar } impl, H: DuplexHash>, R: RngCore + CryptoRng, const N: usize> - FieldWriter> for Arthur> + FieldWriter> for Arthur, R> { fn add_scalars(&mut self, input: &[Fp]) -> ProofResult<()> { self.public_units(input)?; @@ -26,13 +26,13 @@ impl, H: DuplexHash>, R: RngCore + CryptoRng, const N: u } } -impl GroupWriter for Arthur +impl GroupWriter for Arthur where G: CurveGroup, H: DuplexHash, G::BaseField: PrimeField, R: RngCore + CryptoRng, - Arthur: GroupPublic>, + Arthur: GroupPublic>, { #[inline(always)] fn add_points(&mut self, input: &[G]) -> ProofResult<()> { @@ -43,12 +43,12 @@ where } impl, C2: FpConfig, const N: usize> GroupWriter - for Arthur> + for Arthur, R> where G: CurveGroup>, H: DuplexHash>, R: RngCore + CryptoRng, - Arthur>: GroupPublic + FieldWriter, + Arthur, R>: GroupPublic + FieldWriter, { #[inline(always)] fn add_points(&mut self, input: &[G]) -> ProofResult<()> { diff --git a/src/plugins/group/writer.rs b/src/plugins/group/writer.rs index 92a56c5..7e4c04e 100644 --- a/src/plugins/group/writer.rs +++ b/src/plugins/group/writer.rs @@ -4,7 +4,7 @@ use rand::{CryptoRng, RngCore}; use super::{FieldPublic, FieldWriter, GroupPublic, GroupWriter}; use crate::{Arthur, ByteWriter, DuplexHash, ProofResult}; -impl FieldWriter for Arthur +impl FieldWriter for Arthur where F: PrimeField, H: DuplexHash, @@ -17,7 +17,7 @@ where } } -impl GroupPublic for Arthur +impl GroupPublic for Arthur where G: Group + GroupEncoding, H: DuplexHash, @@ -34,7 +34,7 @@ where } } -impl GroupWriter for Arthur +impl GroupWriter for Arthur where G: Group + GroupEncoding, H: DuplexHash,