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}