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}