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 algebra::{groups::Group, Field};
  2use r1cs_core::{ConstraintSystem, SynthesisError};
  3use r1cs_std::prelude::*;
  4
  5use crate::signature::SigRandomizePkGadget;
  6
  7use std::{borrow::Borrow, marker::PhantomData};
  8
  9use crate::signature::schnorr::{
 10    SchnorrPublicKey, SchnorrSigParameters, SchnorrSignature,
 11};
 12use digest::Digest;
 13
 14pub struct SchnorrSigGadgetParameters<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
 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>>(cs: CS, f: F) -> Result<Self, SynthesisError>
113    where
114        F: FnOnce() -> Result<T, SynthesisError>,
115        T: Borrow<SchnorrSigParameters<G, D>>,
116    {
117        let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
118        Ok(Self {
119            generator,
120            _engine: PhantomData,
121            _group: PhantomData,
122        })
123    }
124}
125
126impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
127where
128    G: Group,
129    ConstraintF: Field,
130    GG: GroupGadget<G, ConstraintF>,
131{
132    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
133    where
134        F: FnOnce() -> Result<T, SynthesisError>,
135        T: Borrow<SchnorrPublicKey<G>>,
136    {
137        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
138        Ok(Self {
139            pub_key,
140            _engine: PhantomData,
141            _group: PhantomData,
142        })
143    }
144
145    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
146    where
147        F: FnOnce() -> Result<T, SynthesisError>,
148        T: Borrow<SchnorrPublicKey<G>>,
149    {
150        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
151        Ok(Self {
152            pub_key,
153            _engine: PhantomData,
154            _group: PhantomData,
155        })
156    }
157}
158
159impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
160where
161    G: Group,
162    ConstraintF: Field,
163    GG: GroupGadget<G, ConstraintF>,
164{
165    #[inline]
166    fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
167        &self,
168        mut cs: CS,
169        other: &Self,
170        condition: &Boolean,
171    ) -> Result<(), SynthesisError> {
172        self.pub_key.conditional_enforce_equal(
173            &mut cs.ns(|| "PubKey equality"),
174            &other.pub_key,
175            condition,
176        )?;
177        Ok(())
178    }
179
180    fn cost() -> usize {
181        <GG as ConditionalEqGadget<ConstraintF>>::cost()
182    }
183}
184
185impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
186where
187    G: Group,
188    ConstraintF: Field,
189    GG: GroupGadget<G, ConstraintF>,
190{
191}
192
193impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
194where
195    G: Group,
196    ConstraintF: Field,
197    GG: GroupGadget<G, ConstraintF>,
198{
199    fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
200        self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
201    }
202
203    fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
204        &self,
205        mut cs: CS,
206    ) -> Result<Vec<UInt8>, SynthesisError> {
207        self.pub_key
208            .to_bytes_strict(&mut cs.ns(|| "PubKey To Bytes"))
209    }
210}