arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/crypto-primitives/src/signature/schnorr/constraints.rs
crypto-primitives/src/signature/schnorr/constraints.rsRaw
  1use crate::Vec;
  2use algebra_core::{groups::Group, Field};
  3use r1cs_core::{ConstraintSystem, SynthesisError};
  4use r1cs_std::prelude::*;
  5
  6use crate::signature::SigRandomizePkGadget;
  7
  8use core::{borrow::Borrow, marker::PhantomData};
  9
 10use crate::signature::schnorr::{SchnorrPublicKey, SchnorrSigParameters, SchnorrSignature};
 11use digest::Digest;
 12
 13pub struct SchnorrSigGadgetParameters<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
 14{
 15    generator: GG,
 16    _group: PhantomData<*const G>,
 17    _engine: PhantomData<*const ConstraintF>,
 18}
 19
 20impl<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> Clone
 21    for SchnorrSigGadgetParameters<G, ConstraintF, GG>
 22{
 23    fn clone(&self) -> Self {
 24        Self {
 25            generator: self.generator.clone(),
 26            _group: PhantomData,
 27            _engine: PhantomData,
 28        }
 29    }
 30}
 31
 32#[derive(Derivative)]
 33#[derivative(
 34    Debug(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 35    Clone(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 36    PartialEq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 37    Eq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>")
 38)]
 39pub struct SchnorrSigGadgetPk<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
 40    pub_key: GG,
 41    #[doc(hidden)]
 42    _group: PhantomData<*const G>,
 43    #[doc(hidden)]
 44    _engine: PhantomData<*const ConstraintF>,
 45}
 46
 47pub struct SchnorrRandomizePkGadget<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
 48    #[doc(hidden)]
 49    _group: PhantomData<*const G>,
 50    #[doc(hidden)]
 51    _group_gadget: PhantomData<*const GG>,
 52    #[doc(hidden)]
 53    _engine: PhantomData<*const ConstraintF>,
 54}
 55
 56impl<G, GG, D, ConstraintF> SigRandomizePkGadget<SchnorrSignature<G, D>, ConstraintF>
 57    for SchnorrRandomizePkGadget<G, ConstraintF, GG>
 58where
 59    G: Group,
 60    GG: GroupGadget<G, ConstraintF>,
 61    D: Digest + Send + Sync,
 62    ConstraintF: Field,
 63{
 64    type ParametersGadget = SchnorrSigGadgetParameters<G, ConstraintF, GG>;
 65    type PublicKeyGadget = SchnorrSigGadgetPk<G, ConstraintF, GG>;
 66
 67    fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
 68        mut cs: CS,
 69        parameters: &Self::ParametersGadget,
 70        public_key: &Self::PublicKeyGadget,
 71        randomness: &[UInt8],
 72    ) -> Result<Self::PublicKeyGadget, SynthesisError> {
 73        let base = parameters.generator.clone();
 74        let randomness = randomness
 75            .iter()
 76            .flat_map(|b| b.into_bits_le())
 77            .collect::<Vec<_>>();
 78        let rand_pk = base.mul_bits(
 79            &mut cs.ns(|| "Compute Randomizer"),
 80            &public_key.pub_key,
 81            randomness.iter(),
 82        )?;
 83        Ok(SchnorrSigGadgetPk {
 84            pub_key: rand_pk,
 85            _group: PhantomData,
 86            _engine: PhantomData,
 87        })
 88    }
 89}
 90
 91impl<G, ConstraintF, GG, D> AllocGadget<SchnorrSigParameters<G, D>, ConstraintF>
 92    for SchnorrSigGadgetParameters<G, ConstraintF, GG>
 93where
 94    G: Group,
 95    ConstraintF: Field,
 96    GG: GroupGadget<G, ConstraintF>,
 97    D: Digest,
 98{
 99    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
100    where
101        F: FnOnce() -> Result<T, SynthesisError>,
102        T: Borrow<SchnorrSigParameters<G, D>>,
103    {
104        let generator = GG::alloc_checked(cs, || f().map(|pp| pp.borrow().generator))?;
105        Ok(Self {
106            generator,
107            _engine: PhantomData,
108            _group: PhantomData,
109        })
110    }
111
112    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
113        cs: CS,
114        f: F,
115    ) -> Result<Self, SynthesisError>
116    where
117        F: FnOnce() -> Result<T, SynthesisError>,
118        T: Borrow<SchnorrSigParameters<G, D>>,
119    {
120        let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
121        Ok(Self {
122            generator,
123            _engine: PhantomData,
124            _group: PhantomData,
125        })
126    }
127}
128
129impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF>
130    for SchnorrSigGadgetPk<G, ConstraintF, GG>
131where
132    G: Group,
133    ConstraintF: Field,
134    GG: GroupGadget<G, ConstraintF>,
135{
136    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
137    where
138        F: FnOnce() -> Result<T, SynthesisError>,
139        T: Borrow<SchnorrPublicKey<G>>,
140    {
141        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
142        Ok(Self {
143            pub_key,
144            _engine: PhantomData,
145            _group: PhantomData,
146        })
147    }
148
149    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
150        cs: CS,
151        f: F,
152    ) -> Result<Self, SynthesisError>
153    where
154        F: FnOnce() -> Result<T, SynthesisError>,
155        T: Borrow<SchnorrPublicKey<G>>,
156    {
157        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
158        Ok(Self {
159            pub_key,
160            _engine: PhantomData,
161            _group: PhantomData,
162        })
163    }
164}
165
166impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
167where
168    G: Group,
169    ConstraintF: Field,
170    GG: GroupGadget<G, ConstraintF>,
171{
172    #[inline]
173    fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
174        &self,
175        mut cs: CS,
176        other: &Self,
177        condition: &Boolean,
178    ) -> Result<(), SynthesisError> {
179        self.pub_key.conditional_enforce_equal(
180            &mut cs.ns(|| "PubKey equality"),
181            &other.pub_key,
182            condition,
183        )?;
184        Ok(())
185    }
186
187    fn cost() -> usize {
188        <GG as ConditionalEqGadget<ConstraintF>>::cost()
189    }
190}
191
192impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
193where
194    G: Group,
195    ConstraintF: Field,
196    GG: GroupGadget<G, ConstraintF>,
197{
198}
199
200impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
201where
202    G: Group,
203    ConstraintF: Field,
204    GG: GroupGadget<G, ConstraintF>,
205{
206    fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
207        &self,
208        mut cs: CS,
209    ) -> Result<Vec<UInt8>, SynthesisError> {
210        self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
211    }
212}