1use core::borrow::Borrow;
20use core::ops::MulAssign;
21
22use alloc::{vec, vec::Vec};
23
24use ark_ec::hashing::curve_maps::wb::{WBConfig, WBMap};
25use ark_ec::hashing::{
26 map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher},
27 HashToCurve,
28};
29use ark_ec::{
30 pairing::{MillerLoopOutput, Pairing, PairingOutput},
31 AffineRepr, CurveGroup,
32};
33use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
34use ark_ff::{Field, PrimeField, UniformRand, Zero};
35use ark_serialize::CanonicalSerialize;
36use rand::Rng;
37use rand_core::RngCore;
38
39use core::fmt::Debug;
40
41use sha2::Sha256; use ark_ec::bls12::Bls12Config;
44use core::marker::PhantomData;
45
46pub trait EngineBLS {
68 type Engine: Pairing; type Scalar: PrimeField; type PublicKeyGroupBaseField: Field;
76 type PublicKeyGroupAffine: AffineRepr<ScalarField = Self::Scalar, Group = Self::PublicKeyGroup>
77 + From<Self::PublicKeyGroup>
78 + Into<Self::PublicKeyGroup>
79 + Into<Self::PublicKeyPrepared>;
80 type PublicKeyGroup: CurveGroup<
83 Affine = Self::PublicKeyGroupAffine,
84 ScalarField = Self::Scalar,
85 BaseField = Self::PublicKeyGroupBaseField,
86 > + From<Self::PublicKeyGroupAffine>
87 + Into<Self::PublicKeyGroupAffine>
88 + MulAssign<Self::Scalar>;
89
90 type PublicKeyPrepared: Default + Clone + Send + Sync + Debug + From<Self::PublicKeyGroupAffine>;
91
92 const PUBLICKEY_SERIALIZED_SIZE: usize;
93 const SECRET_KEY_SIZE: usize;
94
95 const CURVE_NAME: &'static [u8];
97 const SIG_GROUP_NAME: &'static [u8];
98 const CIPHER_SUIT_DOMAIN_SEPARATION: &'static [u8];
99
100 type SignatureGroupBaseField: Field;
106
107 type SignatureGroupAffine: AffineRepr<ScalarField = Self::Scalar, Group = Self::SignatureGroup>
108 + From<Self::SignatureGroup>
109 + Into<Self::SignatureGroup>
110 + Into<Self::SignaturePrepared>;
111
112 type SignatureGroup: CurveGroup<
113 Affine = Self::SignatureGroupAffine,
114 ScalarField = Self::Scalar,
115 BaseField = Self::SignatureGroupBaseField,
116 > + Into<Self::SignatureGroupAffine>
117 + From<Self::SignatureGroupAffine>
118 + MulAssign<Self::Scalar>;
119
120 type SignaturePrepared: Default + Clone + Send + Sync + Debug + From<Self::SignatureGroupAffine>;
121
122 const SIGNATURE_SERIALIZED_SIZE: usize;
123
124 type HashToSignatureField: HashToField<Self::SignatureGroupBaseField>;
125 type MapToSignatureCurve: MapToCurve<Self::SignatureGroup>;
126
127 fn generate<R: Rng + RngCore>(rng: &mut R) -> Self::Scalar {
129 Self::Scalar::rand(rng)
130 }
131
132 fn hash_to_curve_map() -> MapToCurveBasedHasher<
134 Self::SignatureGroup,
135 Self::HashToSignatureField,
136 Self::MapToSignatureCurve,
137 >;
138
139 fn hash_to_signature_curve<M: Borrow<[u8]>>(message: M) -> Self::SignatureGroup {
141 Self::hash_to_curve_map()
142 .hash(message.borrow())
143 .unwrap()
144 .into_group()
145 }
146
147 fn miller_loop<'a, I>(i: I) -> MillerLoopOutput<Self::Engine>
150 where
151 Self::PublicKeyPrepared: 'a,
152 Self::SignaturePrepared: 'a,
153 I: IntoIterator<
154 Item = &'a (
155 <Self as EngineBLS>::PublicKeyPrepared,
156 Self::SignaturePrepared,
157 ),
158 >;
159
160 fn final_exponentiation(
162 e: MillerLoopOutput<Self::Engine>,
163 ) -> Option<PairingOutput<Self::Engine>> {
164 Self::Engine::final_exponentiation(e)
165 }
166
167 fn pairing<G1, G2>(p: G1, q: G2) -> <Self::Engine as Pairing>::TargetField
170 where
171 G1: Into<<Self::PublicKeyGroup as CurveGroup>::Affine>,
172 G2: Into<<Self::SignatureGroup as CurveGroup>::Affine>;
173 fn verify_prepared<'a, I>(signature: Self::SignaturePrepared, inputs: I) -> bool
189 where
190 Self::PublicKeyPrepared: 'a,
191 Self::SignaturePrepared: 'a,
192 I: IntoIterator<Item = &'a (Self::PublicKeyPrepared, Self::SignaturePrepared)>,
193 {
194 let lhs: [_; 1] = [(
195 Self::minus_generator_of_public_key_group_prepared(),
196 signature,
197 )];
198 Self::final_exponentiation(Self::miller_loop(inputs.into_iter().map(|t| t).chain(&lhs)))
199 .unwrap()
200 == (PairingOutput::<Self::Engine>::zero()) }
202
203 fn minus_generator_of_public_key_group_prepared() -> Self::PublicKeyPrepared;
205
206 fn generator_of_signature_group() -> Self::SignatureGroup {
208 <Self::SignatureGroup as CurveGroup>::Affine::generator().into()
209 }
210
211 fn prepare_public_key(g: impl Into<Self::PublicKeyGroupAffine>) -> Self::PublicKeyPrepared {
216 let g_affine: Self::PublicKeyGroupAffine = g.into();
217 Self::PublicKeyPrepared::from(g_affine)
218 }
219
220 fn prepare_signature(g: impl Into<Self::SignatureGroupAffine>) -> Self::SignaturePrepared {
225 let g_affine: Self::SignatureGroupAffine = g.into();
226 Self::SignaturePrepared::from(g_affine)
227 }
228
229 fn signature_point_to_byte(point: &Self::SignatureGroup) -> Vec<u8> {
231 let mut point_as_bytes = vec![0; Self::SIGNATURE_SERIALIZED_SIZE];
232 let point_affine = point.into_affine();
233 point_affine
234 .serialize_compressed(&mut point_as_bytes[..])
235 .unwrap();
236 point_as_bytes
237 }
238
239 fn public_key_point_to_byte(point: &Self::PublicKeyGroup) -> Vec<u8> {
240 let mut point_as_bytes = vec![0; Self::PUBLICKEY_SERIALIZED_SIZE];
241 let point_affine = point.into_affine();
242 point_affine
243 .serialize_compressed(&mut point_as_bytes[..])
244 .unwrap();
245 point_as_bytes
246 }
247}
248
249pub type ZBLS = UsualBLS<ark_bls12_381::Bls12_381, ark_bls12_381::Config>;
251pub type BLS377 = UsualBLS<ark_bls12_377::Bls12_377, ark_bls12_377::Config>;
252
253#[derive(Default)]
263pub struct UsualBLS<E: Pairing, P: Bls12Config + CurveExtraConfig>(pub E, PhantomData<fn() -> P>)
264where
265 <P as Bls12Config>::G2Config: WBConfig,
266 WBMap<<P as Bls12Config>::G2Config>: MapToCurve<<E as Pairing>::G2>;
267
268impl<E: Pairing, P: Bls12Config + CurveExtraConfig> EngineBLS for UsualBLS<E, P>
269where
270 <P as Bls12Config>::G2Config: WBConfig,
271 WBMap<<P as Bls12Config>::G2Config>: MapToCurve<<E as Pairing>::G2>,
272{
273 type Engine = E;
274 type Scalar = <Self::Engine as Pairing>::ScalarField;
275
276 type PublicKeyGroup = E::G1;
277 type PublicKeyGroupAffine = E::G1Affine;
278 type PublicKeyPrepared = E::G1Prepared;
279 type PublicKeyGroupBaseField = <<E as Pairing>::G1 as CurveGroup>::BaseField;
280
281 const PUBLICKEY_SERIALIZED_SIZE: usize = 48;
282 const SECRET_KEY_SIZE: usize = 32;
283
284 const CURVE_NAME: &'static [u8] = P::CURVE_NAME;
285 const SIG_GROUP_NAME: &'static [u8] = b"G2";
286 const CIPHER_SUIT_DOMAIN_SEPARATION: &'static [u8] = b"_XMD:SHA-256_SSWU_RO_";
287
288 type SignatureGroup = E::G2;
289 type SignatureGroupAffine = E::G2Affine;
290 type SignaturePrepared = E::G2Prepared;
291 type SignatureGroupBaseField = <<E as Pairing>::G2 as CurveGroup>::BaseField;
292
293 const SIGNATURE_SERIALIZED_SIZE: usize = 96;
294
295 type HashToSignatureField = DefaultFieldHasher<Sha256, 128>;
296 type MapToSignatureCurve = WBMap<P::G2Config>;
297
298 fn miller_loop<'a, I>(i: I) -> MillerLoopOutput<E>
299 where
300 I: IntoIterator<Item = &'a (Self::PublicKeyPrepared, Self::SignaturePrepared)>,
303 {
304 let (i_a, i_b): (Vec<Self::PublicKeyPrepared>, Vec<Self::SignaturePrepared>) =
305 i.into_iter().cloned().unzip();
306
307 E::multi_miller_loop(i_a, i_b)
308 }
309
310 fn pairing<G1, G2>(p: G1, q: G2) -> E::TargetField
311 where
312 G1: Into<E::G1Affine>,
313 G2: Into<E::G2Affine>,
314 {
315 E::pairing(p.into(), q.into()).0
316 }
317
318 fn minus_generator_of_public_key_group_prepared() -> Self::PublicKeyPrepared {
320 let g1_minus_generator = <Self::PublicKeyGroup as CurveGroup>::Affine::generator();
321 <Self::PublicKeyGroup as Into<Self::PublicKeyPrepared>>::into(
322 -g1_minus_generator.into_group(),
323 )
324 }
325
326 fn hash_to_curve_map() -> MapToCurveBasedHasher<
327 Self::SignatureGroup,
328 Self::HashToSignatureField,
329 Self::MapToSignatureCurve,
330 > {
331 MapToCurveBasedHasher::<
332 Self::SignatureGroup,
333 DefaultFieldHasher<Sha256, 128>,
334 WBMap<P::G2Config>,
335 >::new(&[1])
336 .unwrap()
337 }
338}
339
340#[derive(Default)]
348pub struct TinyBLS<E: Pairing, P: Bls12Config + CurveExtraConfig>(pub E, PhantomData<fn() -> P>)
349where
350 <P as Bls12Config>::G1Config: WBConfig,
351 WBMap<<P as Bls12Config>::G1Config>: MapToCurve<<E as Pairing>::G1>;
352
353pub trait CurveExtraConfig {
355 const CURVE_NAME: &'static [u8];
356}
357
358impl<E: Pairing, P: Bls12Config + CurveExtraConfig> EngineBLS for TinyBLS<E, P>
359where
360 <P as Bls12Config>::G1Config: WBConfig,
361 WBMap<<P as Bls12Config>::G1Config>: MapToCurve<<E as Pairing>::G1>,
362{
363 type Engine = E;
364 type Scalar = <Self::Engine as Pairing>::ScalarField;
365
366 type SignatureGroup = E::G1;
367 type SignatureGroupAffine = E::G1Affine;
368 type SignaturePrepared = E::G1Prepared;
369 type SignatureGroupBaseField = <<E as Pairing>::G1 as CurveGroup>::BaseField;
370
371 const SIGNATURE_SERIALIZED_SIZE: usize = 48;
372
373 type PublicKeyGroup = E::G2;
374 type PublicKeyGroupAffine = E::G2Affine;
375 type PublicKeyPrepared = E::G2Prepared;
376 type PublicKeyGroupBaseField = <<E as Pairing>::G2 as CurveGroup>::BaseField;
377
378 const PUBLICKEY_SERIALIZED_SIZE: usize = 96;
379 const SECRET_KEY_SIZE: usize = 32;
380
381 const CURVE_NAME: &'static [u8] = P::CURVE_NAME;
382 const SIG_GROUP_NAME: &'static [u8] = b"G1";
383 const CIPHER_SUIT_DOMAIN_SEPARATION: &'static [u8] = b"_XMD:SHA-256_SSWU_RO_";
384
385 type HashToSignatureField = DefaultFieldHasher<Sha256, 128>;
386 type MapToSignatureCurve = WBMap<P::G1Config>;
387
388 fn miller_loop<'a, I>(i: I) -> MillerLoopOutput<E>
389 where
390 I: IntoIterator<Item = &'a (Self::PublicKeyPrepared, Self::SignaturePrepared)>,
391 {
392 let (i_a, i_b): (Vec<Self::PublicKeyPrepared>, Vec<Self::SignaturePrepared>) =
396 i.into_iter().cloned().unzip();
397
398 E::multi_miller_loop(i_b, i_a) }
400
401 fn pairing<G2, G1>(p: G2, q: G1) -> E::TargetField
402 where
403 G1: Into<E::G1Affine>,
404 G2: Into<E::G2Affine>,
405 {
406 E::pairing(q.into(), p.into()).0
407 }
408
409 fn minus_generator_of_public_key_group_prepared() -> Self::PublicKeyPrepared {
411 let g2_minus_generator = <Self::PublicKeyGroup as CurveGroup>::Affine::generator();
412 <Self::PublicKeyGroup as Into<Self::PublicKeyPrepared>>::into(
413 -g2_minus_generator.into_group(),
414 )
415 }
416
417 fn hash_to_curve_map() -> MapToCurveBasedHasher<
418 Self::SignatureGroup,
419 Self::HashToSignatureField,
420 Self::MapToSignatureCurve,
421 > {
422 MapToCurveBasedHasher::<
423 Self::SignatureGroup,
424 DefaultFieldHasher<Sha256, 128>,
425 WBMap<P::G1Config>,
426 >::new(&[1])
427 .unwrap()
428 }
429}
430
431impl CurveExtraConfig for ark_bls12_377::Config {
433 const CURVE_NAME: &'static [u8] = b"BLS12377";
434}
435pub type TinyBLS377 = TinyBLS<ark_bls12_377::Bls12_377, ark_bls12_377::Config>;
436impl CurveExtraConfig for ark_bls12_381::Config {
438 const CURVE_NAME: &'static [u8] = b"BLS12381";
439}
440pub type TinyBLS381 = TinyBLS<ark_bls12_381::Bls12_381, ark_bls12_381::Config>;