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_constant<T, CS: ConstraintSystem<ConstraintF>>(
100 cs: CS,
101 val: T,
102 ) -> Result<Self, SynthesisError>
103 where
104 T: Borrow<SchnorrSigParameters<G, D>>,
105 {
106 let generator = GG::alloc_constant(cs, val.borrow().generator)?;
107 Ok(Self {
108 generator,
109 _engine: PhantomData,
110 _group: PhantomData,
111 })
112 }
113
114 fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
115 where
116 F: FnOnce() -> Result<T, SynthesisError>,
117 T: Borrow<SchnorrSigParameters<G, D>>,
118 {
119 let generator = GG::alloc_checked(cs, || f().map(|pp| pp.borrow().generator))?;
120 Ok(Self {
121 generator,
122 _engine: PhantomData,
123 _group: PhantomData,
124 })
125 }
126
127 fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
128 cs: CS,
129 f: F,
130 ) -> Result<Self, SynthesisError>
131 where
132 F: FnOnce() -> Result<T, SynthesisError>,
133 T: Borrow<SchnorrSigParameters<G, D>>,
134 {
135 let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
136 Ok(Self {
137 generator,
138 _engine: PhantomData,
139 _group: PhantomData,
140 })
141 }
142}
143
144impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF>
145 for SchnorrSigGadgetPk<G, ConstraintF, GG>
146where
147 G: Group,
148 ConstraintF: Field,
149 GG: GroupGadget<G, ConstraintF>,
150{
151 fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
152 cs: CS,
153 val: T,
154 ) -> Result<Self, SynthesisError>
155 where
156 T: Borrow<SchnorrPublicKey<G>>,
157 {
158 let pub_key = GG::alloc_constant(cs, val.borrow())?;
159 Ok(Self {
160 pub_key,
161 _engine: PhantomData,
162 _group: PhantomData,
163 })
164 }
165
166 fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
167 where
168 F: FnOnce() -> Result<T, SynthesisError>,
169 T: Borrow<SchnorrPublicKey<G>>,
170 {
171 let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
172 Ok(Self {
173 pub_key,
174 _engine: PhantomData,
175 _group: PhantomData,
176 })
177 }
178
179 fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
180 cs: CS,
181 f: F,
182 ) -> Result<Self, SynthesisError>
183 where
184 F: FnOnce() -> Result<T, SynthesisError>,
185 T: Borrow<SchnorrPublicKey<G>>,
186 {
187 let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
188 Ok(Self {
189 pub_key,
190 _engine: PhantomData,
191 _group: PhantomData,
192 })
193 }
194}
195
196impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
197where
198 G: Group,
199 ConstraintF: Field,
200 GG: GroupGadget<G, ConstraintF>,
201{
202 #[inline]
203 fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
204 &self,
205 mut cs: CS,
206 other: &Self,
207 condition: &Boolean,
208 ) -> Result<(), SynthesisError> {
209 self.pub_key.conditional_enforce_equal(
210 &mut cs.ns(|| "PubKey equality"),
211 &other.pub_key,
212 condition,
213 )?;
214 Ok(())
215 }
216
217 fn cost() -> usize {
218 <GG as ConditionalEqGadget<ConstraintF>>::cost()
219 }
220}
221
222impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
223where
224 G: Group,
225 ConstraintF: Field,
226 GG: GroupGadget<G, ConstraintF>,
227{
228}
229
230impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
231where
232 G: Group,
233 ConstraintF: Field,
234 GG: GroupGadget<G, ConstraintF>,
235{
236 fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
237 &self,
238 mut cs: CS,
239 ) -> Result<Vec<UInt8>, SynthesisError> {
240 self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
241 }
242}