use crate::Vec; use algebra_core::{Field, ProjectiveCurve}; use r1cs_core::{Namespace, SynthesisError}; use r1cs_std::prelude::*; use crate::signature::SigRandomizePkGadget; use core::{borrow::Borrow, marker::PhantomData}; use crate::signature::schnorr::{Parameters, PublicKey, Schnorr}; use digest::Digest; type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Clone)] pub struct ParametersVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { generator: GC, _curve: PhantomData, } #[derive(Derivative)] #[derivative( Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") )] pub struct PublicKeyVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { pub_key: GC, #[doc(hidden)] _group: PhantomData<*const C>, } pub struct SchnorrRandomizePkGadget>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { #[doc(hidden)] _group: PhantomData<*const C>, #[doc(hidden)] _group_gadget: PhantomData<*const GC>, } impl SigRandomizePkGadget, ConstraintF> for SchnorrRandomizePkGadget where C: ProjectiveCurve, GC: CurveVar>, D: Digest + Send + Sync, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { type ParametersVar = ParametersVar; type PublicKeyVar = PublicKeyVar; fn randomize( parameters: &Self::ParametersVar, public_key: &Self::PublicKeyVar, randomness: &[UInt8>], ) -> Result { let base = parameters.generator.clone(); let randomness = randomness .iter() .flat_map(|b| b.to_bits_le().unwrap()) .collect::>(); let rand_pk = &public_key.pub_key + &base.scalar_mul_le(randomness.iter())?; Ok(PublicKeyVar { pub_key: rand_pk, _group: PhantomData, }) } } impl AllocVar, ConstraintF> for ParametersVar where C: ProjectiveCurve, GC: CurveVar>, D: Digest, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { let generator = GC::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?; Ok(Self { generator, _curve: PhantomData, }) } } impl AllocVar, ConstraintF> for PublicKeyVar where C: ProjectiveCurve, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { let pub_key = GC::new_variable(cs, f, mode)?; Ok(Self { pub_key, _group: PhantomData, }) } } impl EqGadget> for PublicKeyVar where C: ProjectiveCurve, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { #[inline] fn is_eq(&self, other: &Self) -> Result>, SynthesisError> { self.pub_key.is_eq(&other.pub_key) } #[inline] fn conditional_enforce_equal( &self, other: &Self, condition: &Boolean>, ) -> Result<(), SynthesisError> { self.pub_key .conditional_enforce_equal(&other.pub_key, condition) } #[inline] fn conditional_enforce_not_equal( &self, other: &Self, condition: &Boolean>, ) -> Result<(), SynthesisError> { self.pub_key .conditional_enforce_not_equal(&other.pub_key, condition) } } impl ToBytesGadget> for PublicKeyVar where C: ProjectiveCurve, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { fn to_bytes(&self) -> Result>>, SynthesisError> { self.pub_key.to_bytes() } }