1#![cfg_attr(not(feature = "std"), no_std)]
6#![allow(non_upper_case_globals)]
7#![allow(non_camel_case_types)]
8#![allow(non_snake_case)]
9#![allow(unexpected_cfgs)]
10
11extern crate alloc;
12
13use alloc::boxed::Box;
14use alloc::vec;
15use alloc::vec::Vec;
16use core::any::Any;
17use core::marker::PhantomData;
18use core::mem::{transmute, MaybeUninit};
19use core::ptr;
20use zeroize::Zeroize;
21
22#[cfg(feature = "std")]
23use std::sync::{atomic::*, mpsc::sync_channel, Arc};
24
25#[cfg(feature = "serde")]
26use serde::{Deserialize, Deserializer, Serialize, Serializer};
27
28#[cfg(feature = "std")]
29trait ThreadPoolExt {
30 fn joined_execute<'any, F>(&self, job: F)
31 where
32 F: FnOnce() + Send + 'any;
33}
34
35#[cfg(all(not(feature = "no-threads"), feature = "std"))]
36mod mt {
37 use super::*;
38 use std::sync::{Mutex, Once};
39 use threadpool::ThreadPool;
40
41 pub fn da_pool() -> ThreadPool {
42 static INIT: Once = Once::new();
43 static mut POOL: *const Mutex<ThreadPool> = ptr::null();
44
45 INIT.call_once(|| {
46 let pool = Mutex::new(ThreadPool::default());
47 unsafe { POOL = transmute::<Box<_>, *const _>(Box::new(pool)) };
48 });
49 unsafe { (*POOL).lock().unwrap().clone() }
50 }
51
52 type Thunk<'any> = Box<dyn FnOnce() + Send + 'any>;
53
54 impl ThreadPoolExt for ThreadPool {
55 fn joined_execute<'scope, F>(&self, job: F)
56 where
57 F: FnOnce() + Send + 'scope,
58 {
59 self.execute(unsafe {
62 transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(job))
63 })
64 }
65 }
66}
67
68#[cfg(all(feature = "no-threads", feature = "std"))]
69mod mt {
70 use super::*;
71
72 pub struct EmptyPool {}
73
74 pub fn da_pool() -> EmptyPool {
75 EmptyPool {}
76 }
77
78 impl EmptyPool {
79 pub fn max_count(&self) -> usize {
80 1
81 }
82 }
83
84 impl ThreadPoolExt for EmptyPool {
85 fn joined_execute<'scope, F>(&self, job: F)
86 where
87 F: FnOnce() + Send + 'scope,
88 {
89 job()
90 }
91 }
92}
93
94include!("bindings.rs");
95
96impl PartialEq for blst_p1 {
97 fn eq(&self, other: &Self) -> bool {
98 unsafe { blst_p1_is_equal(self, other) }
99 }
100}
101
102impl PartialEq for blst_p1_affine {
103 fn eq(&self, other: &Self) -> bool {
104 unsafe { blst_p1_affine_is_equal(self, other) }
105 }
106}
107
108impl PartialEq for blst_p2 {
109 fn eq(&self, other: &Self) -> bool {
110 unsafe { blst_p2_is_equal(self, other) }
111 }
112}
113
114impl PartialEq for blst_p2_affine {
115 fn eq(&self, other: &Self) -> bool {
116 unsafe { blst_p2_affine_is_equal(self, other) }
117 }
118}
119
120impl Default for blst_fp12 {
121 fn default() -> Self {
122 unsafe { *blst_fp12_one() }
123 }
124}
125
126impl PartialEq for blst_fp12 {
127 fn eq(&self, other: &Self) -> bool {
128 unsafe { blst_fp12_is_equal(self, other) }
129 }
130}
131
132impl core::ops::Mul for blst_fp12 {
133 type Output = Self;
134
135 fn mul(self, other: Self) -> Self {
136 let mut out = MaybeUninit::<blst_fp12>::uninit();
137 unsafe {
138 blst_fp12_mul(out.as_mut_ptr(), &self, &other);
139 out.assume_init()
140 }
141 }
142}
143
144impl core::ops::MulAssign for blst_fp12 {
145 fn mul_assign(&mut self, other: Self) {
146 unsafe { blst_fp12_mul(self, self, &other) }
147 }
148}
149
150impl blst_fp12 {
151 pub fn miller_loop(q: &blst_p2_affine, p: &blst_p1_affine) -> Self {
152 let mut out = MaybeUninit::<blst_fp12>::uninit();
153 unsafe {
154 blst_miller_loop(out.as_mut_ptr(), q, p);
155 out.assume_init()
156 }
157 }
158
159 #[cfg(not(feature = "std"))]
160 pub fn miller_loop_n(q: &[blst_p2_affine], p: &[blst_p1_affine]) -> Self {
161 let n_elems = q.len();
162 if n_elems != p.len() || n_elems == 0 {
163 panic!("inputs' lengths mismatch");
164 }
165 let qs: [*const _; 2] = [&q[0], ptr::null()];
166 let ps: [*const _; 2] = [&p[0], ptr::null()];
167 let mut out = MaybeUninit::<blst_fp12>::uninit();
168 unsafe {
169 blst_miller_loop_n(out.as_mut_ptr(), &qs[0], &ps[0], n_elems);
170 out.assume_init()
171 }
172 }
173
174 #[cfg(feature = "std")]
175 pub fn miller_loop_n(q: &[blst_p2_affine], p: &[blst_p1_affine]) -> Self {
176 let n_elems = q.len();
177 if n_elems != p.len() || n_elems == 0 {
178 panic!("inputs' lengths mismatch");
179 }
180
181 let pool = mt::da_pool();
182
183 let mut n_workers = pool.max_count();
184 if n_workers == 1 {
185 let qs: [*const _; 2] = [&q[0], ptr::null()];
186 let ps: [*const _; 2] = [&p[0], ptr::null()];
187 let mut out = MaybeUninit::<blst_fp12>::uninit();
188 unsafe {
189 blst_miller_loop_n(out.as_mut_ptr(), &qs[0], &ps[0], n_elems);
190 return out.assume_init();
191 }
192 }
193
194 let counter = Arc::new(AtomicUsize::new(0));
195 let stride = core::cmp::min((n_elems + n_workers - 1) / n_workers, 16);
196 n_workers = core::cmp::min((n_elems + stride - 1) / stride, n_workers);
197 let (tx, rx) = sync_channel(n_workers);
198 for _ in 0..n_workers {
199 let tx = tx.clone();
200 let counter = counter.clone();
201
202 pool.joined_execute(move || {
203 let mut acc = blst_fp12::default();
204 let mut tmp = MaybeUninit::<blst_fp12>::uninit();
205 let mut qs: [*const _; 2] = [ptr::null(), ptr::null()];
206 let mut ps: [*const _; 2] = [ptr::null(), ptr::null()];
207
208 loop {
209 let work = counter.fetch_add(stride, Ordering::Relaxed);
210 if work >= n_elems {
211 break;
212 }
213 let n = core::cmp::min(n_elems - work, stride);
214 qs[0] = &q[work];
215 ps[0] = &p[work];
216 unsafe {
217 blst_miller_loop_n(tmp.as_mut_ptr(), &qs[0], &ps[0], n);
218 acc *= tmp.assume_init();
219 }
220 }
221
222 tx.send(acc).expect("disaster");
223 });
224 }
225
226 let mut acc = rx.recv().unwrap();
227 for _ in 1..n_workers {
228 acc *= rx.recv().unwrap();
229 }
230
231 acc
232 }
233
234 pub fn final_exp(&self) -> Self {
235 let mut out = MaybeUninit::<blst_fp12>::uninit();
236 unsafe {
237 blst_final_exp(out.as_mut_ptr(), self);
238 out.assume_init()
239 }
240 }
241
242 pub fn in_group(&self) -> bool {
243 unsafe { blst_fp12_in_group(self) }
244 }
245
246 pub fn finalverify(a: &Self, b: &Self) -> bool {
247 unsafe { blst_fp12_finalverify(a, b) }
248 }
249
250 pub fn to_bendian(&self) -> [u8; 48 * 12] {
251 let mut out = MaybeUninit::<[u8; 48 * 12]>::uninit();
252 unsafe {
253 blst_bendian_from_fp12(out.as_mut_ptr() as *mut u8, self);
254 out.assume_init()
255 }
256 }
257}
258
259impl blst_scalar {
260 pub fn hash_to(msg: &[u8], dst: &[u8]) -> Option<Self> {
261 unsafe {
262 let mut out = <Self>::default();
263 let mut elem = [0u8; 48];
264 blst_expand_message_xmd(
265 elem.as_mut_ptr(),
266 elem.len(),
267 msg.as_ptr(),
268 msg.len(),
269 dst.as_ptr(),
270 dst.len(),
271 );
272 if blst_scalar_from_be_bytes(&mut out, elem.as_ptr(), elem.len()) {
273 Some(out)
274 } else {
275 None
276 }
277 }
278 }
279}
280
281#[derive(Debug)]
282pub struct Pairing<'p> {
283 v: Box<[u64]>,
284 p: PhantomData<&'p [u8]>,
285}
286
287impl<'p> Pairing<'p> {
288 pub fn new(hash_or_encode: bool, dst: &'p [u8]) -> Self {
289 let v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
290 let mut obj = Self {
291 v: v.into_boxed_slice(),
292 p: PhantomData,
293 };
294 obj.init(hash_or_encode, dst);
295 obj
296 }
297
298 pub fn init(&mut self, hash_or_encode: bool, dst: &'p [u8]) {
299 unsafe {
300 blst_pairing_init(
301 self.ctx(),
302 hash_or_encode,
303 dst.as_ptr(),
304 dst.len(),
305 )
306 }
307 }
308 fn ctx(&mut self) -> *mut blst_pairing {
309 self.v.as_mut_ptr() as *mut blst_pairing
310 }
311 fn const_ctx(&self) -> *const blst_pairing {
312 self.v.as_ptr() as *const blst_pairing
313 }
314
315 pub fn aggregate(
316 &mut self,
317 pk: &dyn Any,
318 pk_validate: bool,
319 sig: &dyn Any,
320 sig_groupcheck: bool,
321 msg: &[u8],
322 aug: &[u8],
323 ) -> BLST_ERROR {
324 if pk.is::<blst_p1_affine>() {
325 unsafe {
326 blst_pairing_chk_n_aggr_pk_in_g1(
327 self.ctx(),
328 match pk.downcast_ref::<blst_p1_affine>() {
329 Some(pk) => pk,
330 None => ptr::null(),
331 },
332 pk_validate,
333 match sig.downcast_ref::<blst_p2_affine>() {
334 Some(sig) => sig,
335 None => ptr::null(),
336 },
337 sig_groupcheck,
338 msg.as_ptr(),
339 msg.len(),
340 aug.as_ptr(),
341 aug.len(),
342 )
343 }
344 } else if pk.is::<blst_p2_affine>() {
345 unsafe {
346 blst_pairing_chk_n_aggr_pk_in_g2(
347 self.ctx(),
348 match pk.downcast_ref::<blst_p2_affine>() {
349 Some(pk) => pk,
350 None => ptr::null(),
351 },
352 pk_validate,
353 match sig.downcast_ref::<blst_p1_affine>() {
354 Some(sig) => sig,
355 None => ptr::null(),
356 },
357 sig_groupcheck,
358 msg.as_ptr(),
359 msg.len(),
360 aug.as_ptr(),
361 aug.len(),
362 )
363 }
364 } else {
365 panic!("whaaaa?")
366 }
367 }
368
369 #[allow(clippy::too_many_arguments)]
370 pub fn mul_n_aggregate(
371 &mut self,
372 pk: &dyn Any,
373 pk_validate: bool,
374 sig: &dyn Any,
375 sig_groupcheck: bool,
376 scalar: &[u8],
377 nbits: usize,
378 msg: &[u8],
379 aug: &[u8],
380 ) -> BLST_ERROR {
381 if scalar.len() < (nbits + 7) / 8 {
382 panic!("scalar length mismatch");
383 }
384
385 if pk.is::<blst_p1_affine>() {
386 unsafe {
387 blst_pairing_chk_n_mul_n_aggr_pk_in_g1(
388 self.ctx(),
389 match pk.downcast_ref::<blst_p1_affine>() {
390 Some(pk) => pk,
391 None => ptr::null(),
392 },
393 pk_validate,
394 match sig.downcast_ref::<blst_p2_affine>() {
395 Some(sig) => sig,
396 None => ptr::null(),
397 },
398 sig_groupcheck,
399 scalar.as_ptr(),
400 nbits,
401 msg.as_ptr(),
402 msg.len(),
403 aug.as_ptr(),
404 aug.len(),
405 )
406 }
407 } else if pk.is::<blst_p2_affine>() {
408 unsafe {
409 blst_pairing_chk_n_mul_n_aggr_pk_in_g2(
410 self.ctx(),
411 match pk.downcast_ref::<blst_p2_affine>() {
412 Some(pk) => pk,
413 None => ptr::null(),
414 },
415 pk_validate,
416 match sig.downcast_ref::<blst_p1_affine>() {
417 Some(sig) => sig,
418 None => ptr::null(),
419 },
420 sig_groupcheck,
421 scalar.as_ptr(),
422 nbits,
423 msg.as_ptr(),
424 msg.len(),
425 aug.as_ptr(),
426 aug.len(),
427 )
428 }
429 } else {
430 panic!("whaaaa?")
431 }
432 }
433
434 pub fn aggregated(gtsig: &mut blst_fp12, sig: &dyn Any) {
435 if sig.is::<blst_p1_affine>() {
436 unsafe {
437 blst_aggregated_in_g1(
438 gtsig,
439 sig.downcast_ref::<blst_p1_affine>().unwrap(),
440 )
441 }
442 } else if sig.is::<blst_p2_affine>() {
443 unsafe {
444 blst_aggregated_in_g2(
445 gtsig,
446 sig.downcast_ref::<blst_p2_affine>().unwrap(),
447 )
448 }
449 } else {
450 panic!("whaaaa?")
451 }
452 }
453
454 pub fn commit(&mut self) {
455 unsafe { blst_pairing_commit(self.ctx()) }
456 }
457
458 pub fn merge(&mut self, ctx1: &Self) -> BLST_ERROR {
459 unsafe { blst_pairing_merge(self.ctx(), ctx1.const_ctx()) }
460 }
461
462 pub fn finalverify(&self, gtsig: Option<&blst_fp12>) -> bool {
463 unsafe {
464 blst_pairing_finalverify(
465 self.const_ctx(),
466 match gtsig {
467 Some(gtsig) => gtsig,
468 None => ptr::null(),
469 },
470 )
471 }
472 }
473
474 pub fn raw_aggregate(&mut self, q: &blst_p2_affine, p: &blst_p1_affine) {
475 unsafe { blst_pairing_raw_aggregate(self.ctx(), q, p) }
476 }
477
478 pub fn as_fp12(&mut self) -> blst_fp12 {
479 unsafe { *blst_pairing_as_fp12(self.ctx()) }
480 }
481}
482
483pub fn uniq(msgs: &[&[u8]]) -> bool {
484 let n_elems = msgs.len();
485
486 if n_elems == 1 {
487 return true;
488 } else if n_elems == 2 {
489 return msgs[0] != msgs[1];
490 }
491
492 let mut v: Vec<u64> = vec![0; unsafe { blst_uniq_sizeof(n_elems) } / 8];
493 let ctx = v.as_mut_ptr() as *mut blst_uniq;
494
495 unsafe { blst_uniq_init(ctx) };
496
497 for msg in msgs.iter() {
498 if !unsafe { blst_uniq_test(ctx, msg.as_ptr(), msg.len()) } {
499 return false;
500 }
501 }
502
503 true
504}
505
506#[cfg(feature = "std")]
507pub fn print_bytes(bytes: &[u8], name: &str) {
508 print!("{} ", name);
509 for b in bytes.iter() {
510 print!("{:02x}", b);
511 }
512 println!();
513}
514
515macro_rules! sig_variant_impl {
516 (
517 $name:expr,
518 $pk:ty,
519 $pk_aff:ty,
520 $sig:ty,
521 $sig_aff:ty,
522 $sk_to_pk:ident,
523 $hash_or_encode:expr,
524 $hash_or_encode_to:ident,
525 $sign:ident,
526 $pk_eq:ident,
527 $sig_eq:ident,
528 $verify:ident,
529 $pk_in_group:ident,
530 $pk_to_aff:ident,
531 $pk_from_aff:ident,
532 $pk_ser:ident,
533 $pk_comp:ident,
534 $pk_deser:ident,
535 $pk_uncomp:ident,
536 $pk_comp_size:expr,
537 $pk_ser_size:expr,
538 $sig_in_group:ident,
539 $sig_to_aff:ident,
540 $sig_from_aff:ident,
541 $sig_ser:ident,
542 $sig_comp:ident,
543 $sig_deser:ident,
544 $sig_uncomp:ident,
545 $sig_comp_size:expr,
546 $sig_ser_size:expr,
547 $pk_add_or_dbl:ident,
548 $pk_add_or_dbl_aff:ident,
549 $pk_cneg:ident,
550 $sig_add_or_dbl:ident,
551 $sig_add_or_dbl_aff:ident,
552 $pk_is_inf:ident,
553 $sig_is_inf:ident,
554 $sig_aggr_in_group:ident,
555 ) => {
556 #[repr(transparent)]
558 #[derive(Default, Debug, Clone, Zeroize)]
559 #[zeroize(drop)]
560 pub struct SecretKey {
561 value: blst_scalar,
562 }
563
564 impl SecretKey {
565 pub fn key_gen(
567 ikm: &[u8],
568 key_info: &[u8],
569 ) -> Result<Self, BLST_ERROR> {
570 if ikm.len() < 32 {
571 return Err(BLST_ERROR::BLST_BAD_ENCODING);
572 }
573 let mut sk = SecretKey::default();
574 unsafe {
575 blst_keygen(
576 &mut sk.value,
577 ikm.as_ptr(),
578 ikm.len(),
579 key_info.as_ptr(),
580 key_info.len(),
581 );
582 }
583 Ok(sk)
584 }
585
586 pub fn key_gen_v3(
587 ikm: &[u8],
588 key_info: &[u8],
589 ) -> Result<Self, BLST_ERROR> {
590 if ikm.len() < 32 {
591 return Err(BLST_ERROR::BLST_BAD_ENCODING);
592 }
593 let mut sk = SecretKey::default();
594 unsafe {
595 blst_keygen_v3(
596 &mut sk.value,
597 ikm.as_ptr(),
598 ikm.len(),
599 key_info.as_ptr(),
600 key_info.len(),
601 );
602 }
603 Ok(sk)
604 }
605
606 pub fn key_gen_v4_5(
607 ikm: &[u8],
608 salt: &[u8],
609 info: &[u8],
610 ) -> Result<Self, BLST_ERROR> {
611 if ikm.len() < 32 {
612 return Err(BLST_ERROR::BLST_BAD_ENCODING);
613 }
614 let mut sk = SecretKey::default();
615 unsafe {
616 blst_keygen_v4_5(
617 &mut sk.value,
618 ikm.as_ptr(),
619 ikm.len(),
620 salt.as_ptr(),
621 salt.len(),
622 info.as_ptr(),
623 info.len(),
624 );
625 }
626 Ok(sk)
627 }
628
629 pub fn key_gen_v5(
630 ikm: &[u8],
631 salt: &[u8],
632 info: &[u8],
633 ) -> Result<Self, BLST_ERROR> {
634 if ikm.len() < 32 {
635 return Err(BLST_ERROR::BLST_BAD_ENCODING);
636 }
637 let mut sk = SecretKey::default();
638 unsafe {
639 blst_keygen_v5(
640 &mut sk.value,
641 ikm.as_ptr(),
642 ikm.len(),
643 salt.as_ptr(),
644 salt.len(),
645 info.as_ptr(),
646 info.len(),
647 );
648 }
649 Ok(sk)
650 }
651
652 pub fn derive_master_eip2333(
653 ikm: &[u8],
654 ) -> Result<Self, BLST_ERROR> {
655 if ikm.len() < 32 {
656 return Err(BLST_ERROR::BLST_BAD_ENCODING);
657 }
658 let mut sk = SecretKey::default();
659 unsafe {
660 blst_derive_master_eip2333(
661 &mut sk.value,
662 ikm.as_ptr(),
663 ikm.len(),
664 );
665 }
666 Ok(sk)
667 }
668
669 pub fn derive_child_eip2333(&self, child_index: u32) -> Self {
670 let mut sk = SecretKey::default();
671 unsafe {
672 blst_derive_child_eip2333(
673 &mut sk.value,
674 &self.value,
675 child_index,
676 );
677 }
678 sk
679 }
680
681 pub fn sk_to_pk(&self) -> PublicKey {
683 let mut pk_aff = PublicKey::default();
685 unsafe {
688 $sk_to_pk(
689 ptr::null_mut(),
691 &mut pk_aff.point,
692 &self.value,
693 );
694 }
695 pk_aff
696 }
697
698 pub fn sign(
700 &self,
701 msg: &[u8],
702 dst: &[u8],
703 aug: &[u8],
704 ) -> Signature {
705 let mut q = <$sig>::default();
707 let mut sig_aff = <$sig_aff>::default();
708 unsafe {
710 $hash_or_encode_to(
711 &mut q,
712 msg.as_ptr(),
713 msg.len(),
714 dst.as_ptr(),
715 dst.len(),
716 aug.as_ptr(),
717 aug.len(),
718 );
719 $sign(ptr::null_mut(), &mut sig_aff, &q, &self.value);
720 }
721 Signature { point: sig_aff }
722 }
723
724 pub fn serialize(&self) -> [u8; 32] {
732 let mut sk_out = [0; 32];
733 unsafe {
734 blst_bendian_from_scalar(sk_out.as_mut_ptr(), &self.value);
735 }
736 sk_out
737 }
738
739 pub fn deserialize(sk_in: &[u8]) -> Result<Self, BLST_ERROR> {
741 let mut sk = blst_scalar::default();
742 if sk_in.len() != 32 {
743 return Err(BLST_ERROR::BLST_BAD_ENCODING);
744 }
745 unsafe {
746 blst_scalar_from_bendian(&mut sk, sk_in.as_ptr());
747 if !blst_sk_check(&sk) {
748 return Err(BLST_ERROR::BLST_BAD_ENCODING);
749 }
750 }
751 Ok(Self { value: sk })
752 }
753
754 pub fn to_bytes(&self) -> [u8; 32] {
755 SecretKey::serialize(&self)
756 }
757
758 pub fn from_bytes(sk_in: &[u8]) -> Result<Self, BLST_ERROR> {
759 SecretKey::deserialize(sk_in)
760 }
761 }
762
763 #[cfg(feature = "serde-secret")]
764 impl Serialize for SecretKey {
765 fn serialize<S: Serializer>(
766 &self,
767 ser: S,
768 ) -> Result<S::Ok, S::Error> {
769 let bytes = zeroize::Zeroizing::new(self.serialize());
770 ser.serialize_bytes(bytes.as_ref())
771 }
772 }
773
774 #[cfg(feature = "serde-secret")]
775 impl<'de> Deserialize<'de> for SecretKey {
776 fn deserialize<D: Deserializer<'de>>(
777 deser: D,
778 ) -> Result<Self, D::Error> {
779 let bytes: &[u8] = Deserialize::deserialize(deser)?;
780 Self::deserialize(bytes).map_err(|e| {
781 <D::Error as serde::de::Error>::custom(format!("{:?}", e))
782 })
783 }
784 }
785
786 impl<'a> From<&'a SecretKey> for &'a blst_scalar {
789 fn from(sk: &'a SecretKey) -> Self {
790 unsafe {
791 transmute::<&SecretKey, Self>(sk)
792 }
793 }
794 }
795
796 impl<'a> core::convert::TryFrom<&'a blst_scalar> for &'a SecretKey {
797 type Error = BLST_ERROR;
798
799 fn try_from(sk: &'a blst_scalar) -> Result<Self, Self::Error> {
800 unsafe {
801 if !blst_sk_check(sk) {
802 return Err(BLST_ERROR::BLST_BAD_ENCODING);
803 }
804 Ok(transmute::<&blst_scalar, Self>(sk))
805 }
806 }
807 }
808
809 #[repr(transparent)]
810 #[derive(Default, Debug, Clone, Copy)]
811 pub struct PublicKey {
812 point: $pk_aff,
813 }
814
815 impl PublicKey {
816 pub fn validate(&self) -> Result<(), BLST_ERROR> {
820 unsafe {
821 if $pk_is_inf(&self.point) {
822 return Err(BLST_ERROR::BLST_PK_IS_INFINITY);
823 }
824 if !$pk_in_group(&self.point) {
825 return Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP);
826 }
827 }
828 Ok(())
829 }
830
831 pub fn key_validate(key: &[u8]) -> Result<Self, BLST_ERROR> {
832 let pk = PublicKey::from_bytes(key)?;
833 pk.validate()?;
834 Ok(pk)
835 }
836
837 pub fn from_aggregate(agg_pk: &AggregatePublicKey) -> Self {
838 let mut pk_aff = <$pk_aff>::default();
839 unsafe {
840 $pk_to_aff(&mut pk_aff, &agg_pk.point);
841 }
842 Self { point: pk_aff }
843 }
844
845 pub fn compress(&self) -> [u8; $pk_comp_size] {
848 let mut pk_comp = [0u8; $pk_comp_size];
849 unsafe {
850 $pk_comp(pk_comp.as_mut_ptr(), &self.point);
851 }
852 pk_comp
853 }
854
855 pub fn serialize(&self) -> [u8; $pk_ser_size] {
856 let mut pk_out = [0u8; $pk_ser_size];
857 unsafe {
858 $pk_ser(pk_out.as_mut_ptr(), &self.point);
859 }
860 pk_out
861 }
862
863 pub fn uncompress(pk_comp: &[u8]) -> Result<Self, BLST_ERROR> {
864 if pk_comp.len() == $pk_comp_size && (pk_comp[0] & 0x80) != 0 {
865 let mut pk = <$pk_aff>::default();
866 let err = unsafe { $pk_uncomp(&mut pk, pk_comp.as_ptr()) };
867 if err != BLST_ERROR::BLST_SUCCESS {
868 return Err(err);
869 }
870 Ok(Self { point: pk })
871 } else {
872 Err(BLST_ERROR::BLST_BAD_ENCODING)
873 }
874 }
875
876 pub fn deserialize(pk_in: &[u8]) -> Result<Self, BLST_ERROR> {
877 if (pk_in.len() == $pk_ser_size && (pk_in[0] & 0x80) == 0)
878 || (pk_in.len() == $pk_comp_size && (pk_in[0] & 0x80) != 0)
879 {
880 let mut pk = <$pk_aff>::default();
881 let err = unsafe { $pk_deser(&mut pk, pk_in.as_ptr()) };
882 if err != BLST_ERROR::BLST_SUCCESS {
883 return Err(err);
884 }
885 Ok(Self { point: pk })
886 } else {
887 Err(BLST_ERROR::BLST_BAD_ENCODING)
888 }
889 }
890
891 pub fn from_bytes(pk_in: &[u8]) -> Result<Self, BLST_ERROR> {
892 PublicKey::deserialize(pk_in)
893 }
894
895 pub fn to_bytes(&self) -> [u8; $pk_comp_size] {
896 self.compress()
897 }
898 }
899
900 impl Eq for PublicKey {}
905
906 impl PartialEq for PublicKey {
907 fn eq(&self, other: &Self) -> bool {
908 unsafe { $pk_eq(&self.point, &other.point) }
909 }
910 }
911
912 #[cfg(feature = "serde")]
913 impl Serialize for PublicKey {
914 fn serialize<S: Serializer>(
915 &self,
916 ser: S,
917 ) -> Result<S::Ok, S::Error> {
918 ser.serialize_bytes(&self.serialize())
919 }
920 }
921
922 #[cfg(feature = "serde")]
923 impl<'de> Deserialize<'de> for PublicKey {
924 fn deserialize<D: Deserializer<'de>>(
925 deser: D,
926 ) -> Result<Self, D::Error> {
927 let bytes: &[u8] = Deserialize::deserialize(deser)?;
928 Self::deserialize(&bytes).map_err(|e| {
929 <D::Error as serde::de::Error>::custom(format!("{:?}", e))
930 })
931 }
932 }
933
934 impl From<PublicKey> for $pk_aff {
935 fn from(pk: PublicKey) -> Self {
936 pk.point
937 }
938 }
939
940 impl<'a> From<&'a PublicKey> for &'a $pk_aff {
941 fn from(pk: &'a PublicKey) -> Self {
942 &pk.point
943 }
944 }
945
946 impl From<$pk_aff> for PublicKey {
947 fn from(point: $pk_aff) -> Self {
948 Self { point }
949 }
950 }
951
952 #[repr(transparent)]
953 #[derive(Debug, Clone, Copy)]
954 pub struct AggregatePublicKey {
955 point: $pk,
956 }
957
958 impl AggregatePublicKey {
959 pub fn from_public_key(pk: &PublicKey) -> Self {
960 let mut agg_pk = <$pk>::default();
961 unsafe {
962 $pk_from_aff(&mut agg_pk, &pk.point);
963 }
964 Self { point: agg_pk }
965 }
966
967 pub fn to_public_key(&self) -> PublicKey {
968 let mut pk = <$pk_aff>::default();
969 unsafe {
970 $pk_to_aff(&mut pk, &self.point);
971 }
972 PublicKey { point: pk }
973 }
974
975 pub fn aggregate(
977 pks: &[&PublicKey],
978 pks_validate: bool,
979 ) -> Result<Self, BLST_ERROR> {
980 if pks.len() == 0 {
981 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
982 }
983 if pks_validate {
984 pks[0].validate()?;
985 }
986 let mut agg_pk = AggregatePublicKey::from_public_key(pks[0]);
987 for s in pks.iter().skip(1) {
988 if pks_validate {
989 s.validate()?;
990 }
991 unsafe {
992 $pk_add_or_dbl_aff(
993 &mut agg_pk.point,
994 &agg_pk.point,
995 &s.point,
996 );
997 }
998 }
999 Ok(agg_pk)
1000 }
1001
1002 pub fn aggregate_with_randomness(
1003 pks: &[PublicKey],
1004 randomness: &[u8],
1005 nbits: usize,
1006 pks_groupcheck: bool,
1007 ) -> Result<Self, BLST_ERROR> {
1008 if pks.len() == 0 {
1009 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1010 }
1011 if pks_groupcheck {
1012 pks.validate()?;
1013 }
1014 Ok(pks.mult(randomness, nbits))
1015 }
1016
1017 pub fn aggregate_serialized(
1018 pks: &[&[u8]],
1019 pks_validate: bool,
1020 ) -> Result<Self, BLST_ERROR> {
1021 if pks.len() == 0 {
1023 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1024 }
1025 let mut pk = if pks_validate {
1026 PublicKey::key_validate(pks[0])?
1027 } else {
1028 PublicKey::from_bytes(pks[0])?
1029 };
1030 let mut agg_pk = AggregatePublicKey::from_public_key(&pk);
1031 for s in pks.iter().skip(1) {
1032 pk = if pks_validate {
1033 PublicKey::key_validate(s)?
1034 } else {
1035 PublicKey::from_bytes(s)?
1036 };
1037 unsafe {
1038 $pk_add_or_dbl_aff(
1039 &mut agg_pk.point,
1040 &agg_pk.point,
1041 &pk.point,
1042 );
1043 }
1044 }
1045 Ok(agg_pk)
1046 }
1047
1048 pub fn add_aggregate(&mut self, agg_pk: &AggregatePublicKey) {
1049 unsafe {
1050 $pk_add_or_dbl(&mut self.point, &self.point, &agg_pk.point);
1051 }
1052 }
1053
1054 pub fn sub_aggregate(&mut self, agg_pk: &AggregatePublicKey) {
1055 unsafe {
1056 let mut tmp = agg_pk.clone();
1057 $pk_cneg(&mut tmp.point, true);
1058 $pk_add_or_dbl(&mut self.point, &self.point, &tmp.point);
1059 }
1060 }
1061
1062 pub fn add_public_key(
1063 &mut self,
1064 pk: &PublicKey,
1065 pk_validate: bool,
1066 ) -> Result<(), BLST_ERROR> {
1067 if pk_validate {
1068 pk.validate()?;
1069 }
1070 unsafe {
1071 $pk_add_or_dbl_aff(&mut self.point, &self.point, &pk.point);
1072 }
1073 Ok(())
1074 }
1075 }
1076
1077 impl From<AggregatePublicKey> for $pk {
1078 fn from(pk: AggregatePublicKey) -> Self {
1079 pk.point
1080 }
1081 }
1082
1083 impl<'a> From<&'a AggregatePublicKey> for &'a $pk {
1084 fn from(pk: &'a AggregatePublicKey) -> Self {
1085 &pk.point
1086 }
1087 }
1088
1089 impl From<$pk> for AggregatePublicKey {
1090 fn from(point: $pk) -> Self {
1091 Self { point }
1092 }
1093 }
1094
1095 #[repr(transparent)]
1096 #[derive(Debug, Clone, Copy)]
1097 pub struct Signature {
1098 point: $sig_aff,
1099 }
1100
1101 impl Signature {
1102 pub fn validate(
1107 &self,
1108 sig_infcheck: bool,
1109 ) -> Result<(), BLST_ERROR> {
1110 unsafe {
1111 if sig_infcheck && $sig_is_inf(&self.point) {
1112 return Err(BLST_ERROR::BLST_PK_IS_INFINITY);
1113 }
1114 if !$sig_in_group(&self.point) {
1115 return Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP);
1116 }
1117 }
1118 Ok(())
1119 }
1120
1121 pub fn sig_validate(
1122 sig: &[u8],
1123 sig_infcheck: bool,
1124 ) -> Result<Self, BLST_ERROR> {
1125 let sig = Signature::from_bytes(sig)?;
1126 sig.validate(sig_infcheck)?;
1127 Ok(sig)
1128 }
1129
1130 pub fn verify(
1131 &self,
1132 sig_groupcheck: bool,
1133 msg: &[u8],
1134 dst: &[u8],
1135 aug: &[u8],
1136 pk: &PublicKey,
1137 pk_validate: bool,
1138 ) -> BLST_ERROR {
1139 let aug_msg = [aug, msg].concat();
1140 self.aggregate_verify(
1141 sig_groupcheck,
1142 &[aug_msg.as_slice()],
1143 dst,
1144 &[pk],
1145 pk_validate,
1146 )
1147 }
1148
1149 #[cfg(not(feature = "std"))]
1150 pub fn aggregate_verify(
1151 &self,
1152 sig_groupcheck: bool,
1153 msgs: &[&[u8]],
1154 dst: &[u8],
1155 pks: &[&PublicKey],
1156 pks_validate: bool,
1157 ) -> BLST_ERROR {
1158 let n_elems = pks.len();
1159 if n_elems == 0 || msgs.len() != n_elems {
1160 return BLST_ERROR::BLST_VERIFY_FAIL;
1161 }
1162
1163 let mut pairing = Pairing::new($hash_or_encode, dst);
1164
1165 let err = pairing.aggregate(
1166 &pks[0].point,
1167 pks_validate,
1168 &self.point,
1169 sig_groupcheck,
1170 &msgs[0],
1171 &[],
1172 );
1173 if err != BLST_ERROR::BLST_SUCCESS {
1174 return err;
1175 }
1176
1177 for i in 1..n_elems {
1178 let err = pairing.aggregate(
1179 &pks[i].point,
1180 pks_validate,
1181 &unsafe { ptr::null::<$sig_aff>().as_ref() },
1182 false,
1183 &msgs[i],
1184 &[],
1185 );
1186 if err != BLST_ERROR::BLST_SUCCESS {
1187 return err;
1188 }
1189 }
1190
1191 pairing.commit();
1192
1193 if pairing.finalverify(None) {
1194 BLST_ERROR::BLST_SUCCESS
1195 } else {
1196 BLST_ERROR::BLST_VERIFY_FAIL
1197 }
1198 }
1199
1200 #[cfg(feature = "std")]
1201 pub fn aggregate_verify(
1202 &self,
1203 sig_groupcheck: bool,
1204 msgs: &[&[u8]],
1205 dst: &[u8],
1206 pks: &[&PublicKey],
1207 pks_validate: bool,
1208 ) -> BLST_ERROR {
1209 let n_elems = pks.len();
1210 if n_elems == 0 || msgs.len() != n_elems {
1211 return BLST_ERROR::BLST_VERIFY_FAIL;
1212 }
1213
1214 let pool = mt::da_pool();
1217 let counter = Arc::new(AtomicUsize::new(0));
1218 let valid = Arc::new(AtomicBool::new(true));
1219 let n_workers = core::cmp::min(pool.max_count(), n_elems);
1220 let (tx, rx) = sync_channel(n_workers);
1221 for _ in 0..n_workers {
1222 let tx = tx.clone();
1223 let counter = counter.clone();
1224 let valid = valid.clone();
1225
1226 pool.joined_execute(move || {
1227 let mut pairing = Pairing::new($hash_or_encode, dst);
1228
1229 while valid.load(Ordering::Relaxed) {
1230 let work = counter.fetch_add(1, Ordering::Relaxed);
1231 if work >= n_elems {
1232 break;
1233 }
1234 if pairing.aggregate(
1235 &pks[work].point,
1236 pks_validate,
1237 &unsafe { ptr::null::<$sig_aff>().as_ref() },
1238 false,
1239 &msgs[work],
1240 &[],
1241 ) != BLST_ERROR::BLST_SUCCESS
1242 {
1243 valid.store(false, Ordering::Relaxed);
1244 break;
1245 }
1246 }
1247 if valid.load(Ordering::Relaxed) {
1248 pairing.commit();
1249 }
1250 tx.send(pairing).expect("disaster");
1251 });
1252 }
1253
1254 if sig_groupcheck && valid.load(Ordering::Relaxed) {
1255 match self.validate(false) {
1256 Err(_err) => valid.store(false, Ordering::Relaxed),
1257 _ => (),
1258 }
1259 }
1260
1261 let mut gtsig = blst_fp12::default();
1262 if valid.load(Ordering::Relaxed) {
1263 Pairing::aggregated(&mut gtsig, &self.point);
1264 }
1265
1266 let mut acc = rx.recv().unwrap();
1267 for _ in 1..n_workers {
1268 acc.merge(&rx.recv().unwrap());
1269 }
1270
1271 if valid.load(Ordering::Relaxed)
1272 && acc.finalverify(Some(>sig))
1273 {
1274 BLST_ERROR::BLST_SUCCESS
1275 } else {
1276 BLST_ERROR::BLST_VERIFY_FAIL
1277 }
1278 }
1279
1280 pub fn fast_aggregate_verify(
1283 &self,
1284 sig_groupcheck: bool,
1285 msg: &[u8],
1286 dst: &[u8],
1287 pks: &[&PublicKey],
1288 ) -> BLST_ERROR {
1289 let agg_pk = match AggregatePublicKey::aggregate(pks, false) {
1290 Ok(agg_sig) => agg_sig,
1291 Err(err) => return err,
1292 };
1293 let pk = agg_pk.to_public_key();
1294 self.aggregate_verify(
1295 sig_groupcheck,
1296 &[msg],
1297 dst,
1298 &[&pk],
1299 false,
1300 )
1301 }
1302
1303 pub fn fast_aggregate_verify_pre_aggregated(
1304 &self,
1305 sig_groupcheck: bool,
1306 msg: &[u8],
1307 dst: &[u8],
1308 pk: &PublicKey,
1309 ) -> BLST_ERROR {
1310 self.aggregate_verify(sig_groupcheck, &[msg], dst, &[pk], false)
1311 }
1312
1313 #[cfg(feature = "std")]
1315 #[allow(clippy::too_many_arguments)]
1316 pub fn verify_multiple_aggregate_signatures(
1317 msgs: &[&[u8]],
1318 dst: &[u8],
1319 pks: &[&PublicKey],
1320 pks_validate: bool,
1321 sigs: &[&Signature],
1322 sigs_groupcheck: bool,
1323 rands: &[blst_scalar],
1324 rand_bits: usize,
1325 ) -> BLST_ERROR {
1326 let n_elems = pks.len();
1327 if n_elems == 0
1328 || msgs.len() != n_elems
1329 || sigs.len() != n_elems
1330 || rands.len() != n_elems
1331 {
1332 return BLST_ERROR::BLST_VERIFY_FAIL;
1333 }
1334
1335 let pool = mt::da_pool();
1338 let counter = Arc::new(AtomicUsize::new(0));
1339 let valid = Arc::new(AtomicBool::new(true));
1340 let n_workers = core::cmp::min(pool.max_count(), n_elems);
1341 let (tx, rx) = sync_channel(n_workers);
1342 for _ in 0..n_workers {
1343 let tx = tx.clone();
1344 let counter = counter.clone();
1345 let valid = valid.clone();
1346
1347 pool.joined_execute(move || {
1348 let mut pairing = Pairing::new($hash_or_encode, dst);
1349
1350 while valid.load(Ordering::Relaxed) {
1353 let work = counter.fetch_add(1, Ordering::Relaxed);
1354 if work >= n_elems {
1355 break;
1356 }
1357
1358 if pairing.mul_n_aggregate(
1359 &pks[work].point,
1360 pks_validate,
1361 &sigs[work].point,
1362 sigs_groupcheck,
1363 &rands[work].b,
1364 rand_bits,
1365 msgs[work],
1366 &[],
1367 ) != BLST_ERROR::BLST_SUCCESS
1368 {
1369 valid.store(false, Ordering::Relaxed);
1370 break;
1371 }
1372 }
1373 if valid.load(Ordering::Relaxed) {
1374 pairing.commit();
1375 }
1376 tx.send(pairing).expect("disaster");
1377 });
1378 }
1379
1380 let mut acc = rx.recv().unwrap();
1381 for _ in 1..n_workers {
1382 acc.merge(&rx.recv().unwrap());
1383 }
1384
1385 if valid.load(Ordering::Relaxed) && acc.finalverify(None) {
1386 BLST_ERROR::BLST_SUCCESS
1387 } else {
1388 BLST_ERROR::BLST_VERIFY_FAIL
1389 }
1390 }
1391
1392 #[cfg(not(feature = "std"))]
1393 #[allow(clippy::too_many_arguments)]
1394 pub fn verify_multiple_aggregate_signatures(
1395 msgs: &[&[u8]],
1396 dst: &[u8],
1397 pks: &[&PublicKey],
1398 pks_validate: bool,
1399 sigs: &[&Signature],
1400 sigs_groupcheck: bool,
1401 rands: &[blst_scalar],
1402 rand_bits: usize,
1403 ) -> BLST_ERROR {
1404 let n_elems = pks.len();
1405 if n_elems == 0
1406 || msgs.len() != n_elems
1407 || sigs.len() != n_elems
1408 || rands.len() != n_elems
1409 {
1410 return BLST_ERROR::BLST_VERIFY_FAIL;
1411 }
1412
1413 let mut pairing = Pairing::new($hash_or_encode, dst);
1416
1417 for i in 0..n_elems {
1418 let err = pairing.mul_n_aggregate(
1419 &pks[i].point,
1420 pks_validate,
1421 &sigs[i].point,
1422 sigs_groupcheck,
1423 &rands[i].b,
1424 rand_bits,
1425 msgs[i],
1426 &[],
1427 );
1428 if err != BLST_ERROR::BLST_SUCCESS {
1429 return err;
1430 }
1431 }
1432
1433 pairing.commit();
1434
1435 if pairing.finalverify(None) {
1436 BLST_ERROR::BLST_SUCCESS
1437 } else {
1438 BLST_ERROR::BLST_VERIFY_FAIL
1439 }
1440 }
1441
1442 pub fn from_aggregate(agg_sig: &AggregateSignature) -> Self {
1443 let mut sig_aff = <$sig_aff>::default();
1444 unsafe {
1445 $sig_to_aff(&mut sig_aff, &agg_sig.point);
1446 }
1447 Self { point: sig_aff }
1448 }
1449
1450 pub fn compress(&self) -> [u8; $sig_comp_size] {
1451 let mut sig_comp = [0; $sig_comp_size];
1452 unsafe {
1453 $sig_comp(sig_comp.as_mut_ptr(), &self.point);
1454 }
1455 sig_comp
1456 }
1457
1458 pub fn serialize(&self) -> [u8; $sig_ser_size] {
1459 let mut sig_out = [0; $sig_ser_size];
1460 unsafe {
1461 $sig_ser(sig_out.as_mut_ptr(), &self.point);
1462 }
1463 sig_out
1464 }
1465
1466 pub fn uncompress(sig_comp: &[u8]) -> Result<Self, BLST_ERROR> {
1467 if sig_comp.len() == $sig_comp_size && (sig_comp[0] & 0x80) != 0
1468 {
1469 let mut sig = <$sig_aff>::default();
1470 let err =
1471 unsafe { $sig_uncomp(&mut sig, sig_comp.as_ptr()) };
1472 if err != BLST_ERROR::BLST_SUCCESS {
1473 return Err(err);
1474 }
1475 Ok(Self { point: sig })
1476 } else {
1477 Err(BLST_ERROR::BLST_BAD_ENCODING)
1478 }
1479 }
1480
1481 pub fn deserialize(sig_in: &[u8]) -> Result<Self, BLST_ERROR> {
1482 if (sig_in.len() == $sig_ser_size && (sig_in[0] & 0x80) == 0)
1483 || (sig_in.len() == $sig_comp_size
1484 && (sig_in[0] & 0x80) != 0)
1485 {
1486 let mut sig = <$sig_aff>::default();
1487 let err = unsafe { $sig_deser(&mut sig, sig_in.as_ptr()) };
1488 if err != BLST_ERROR::BLST_SUCCESS {
1489 return Err(err);
1490 }
1491 Ok(Self { point: sig })
1492 } else {
1493 Err(BLST_ERROR::BLST_BAD_ENCODING)
1494 }
1495 }
1496
1497 pub fn from_bytes(sig_in: &[u8]) -> Result<Self, BLST_ERROR> {
1498 Signature::deserialize(sig_in)
1499 }
1500
1501 pub fn to_bytes(&self) -> [u8; $sig_comp_size] {
1502 self.compress()
1503 }
1504
1505 pub fn subgroup_check(&self) -> bool {
1506 unsafe { $sig_in_group(&self.point) }
1507 }
1508 }
1509
1510 impl Eq for Signature {}
1515
1516 impl PartialEq for Signature {
1517 fn eq(&self, other: &Self) -> bool {
1518 unsafe { $sig_eq(&self.point, &other.point) }
1519 }
1520 }
1521
1522 #[cfg(feature = "serde")]
1523 impl Serialize for Signature {
1524 fn serialize<S: Serializer>(
1525 &self,
1526 ser: S,
1527 ) -> Result<S::Ok, S::Error> {
1528 ser.serialize_bytes(&self.serialize())
1529 }
1530 }
1531
1532 #[cfg(feature = "serde")]
1533 impl<'de> Deserialize<'de> for Signature {
1534 fn deserialize<D: Deserializer<'de>>(
1535 deser: D,
1536 ) -> Result<Self, D::Error> {
1537 let bytes: &[u8] = Deserialize::deserialize(deser)?;
1538 Self::deserialize(&bytes).map_err(|e| {
1539 <D::Error as serde::de::Error>::custom(format!("{:?}", e))
1540 })
1541 }
1542 }
1543
1544 impl From<Signature> for $sig_aff {
1545 fn from(sig: Signature) -> Self {
1546 sig.point
1547 }
1548 }
1549
1550 impl<'a> From<&'a Signature> for &'a $sig_aff {
1551 fn from(sig: &'a Signature) -> Self {
1552 &sig.point
1553 }
1554 }
1555
1556 impl From<$sig_aff> for Signature {
1557 fn from(point: $sig_aff) -> Self {
1558 Self { point }
1559 }
1560 }
1561
1562 #[repr(transparent)]
1563 #[derive(Debug, Clone, Copy)]
1564 pub struct AggregateSignature {
1565 point: $sig,
1566 }
1567
1568 impl AggregateSignature {
1569 pub fn validate(&self) -> Result<(), BLST_ERROR> {
1570 unsafe {
1571 if !$sig_aggr_in_group(&self.point) {
1572 return Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP);
1573 }
1574 }
1575 Ok(())
1576 }
1577
1578 pub fn from_signature(sig: &Signature) -> Self {
1579 let mut agg_sig = <$sig>::default();
1580 unsafe {
1581 $sig_from_aff(&mut agg_sig, &sig.point);
1582 }
1583 Self { point: agg_sig }
1584 }
1585
1586 pub fn to_signature(&self) -> Signature {
1587 let mut sig = <$sig_aff>::default();
1588 unsafe {
1589 $sig_to_aff(&mut sig, &self.point);
1590 }
1591 Signature { point: sig }
1592 }
1593
1594 pub fn aggregate(
1596 sigs: &[&Signature],
1597 sigs_groupcheck: bool,
1598 ) -> Result<Self, BLST_ERROR> {
1599 if sigs.len() == 0 {
1600 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1601 }
1602 if sigs_groupcheck {
1603 sigs[0].validate(false)?;
1607 }
1608 let mut agg_sig = AggregateSignature::from_signature(sigs[0]);
1609 for s in sigs.iter().skip(1) {
1610 if sigs_groupcheck {
1611 s.validate(false)?;
1612 }
1613 unsafe {
1614 $sig_add_or_dbl_aff(
1615 &mut agg_sig.point,
1616 &agg_sig.point,
1617 &s.point,
1618 );
1619 }
1620 }
1621 Ok(agg_sig)
1622 }
1623
1624 pub fn aggregate_with_randomness(
1625 sigs: &[Signature],
1626 randomness: &[u8],
1627 nbits: usize,
1628 sigs_groupcheck: bool,
1629 ) -> Result<Self, BLST_ERROR> {
1630 if sigs.len() == 0 {
1631 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1632 }
1633 if sigs_groupcheck {
1634 sigs.validate()?;
1635 }
1636 Ok(sigs.mult(randomness, nbits))
1637 }
1638
1639 pub fn aggregate_serialized(
1640 sigs: &[&[u8]],
1641 sigs_groupcheck: bool,
1642 ) -> Result<Self, BLST_ERROR> {
1643 if sigs.len() == 0 {
1645 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1646 }
1647 let mut sig = if sigs_groupcheck {
1648 Signature::sig_validate(sigs[0], false)?
1649 } else {
1650 Signature::from_bytes(sigs[0])?
1651 };
1652 let mut agg_sig = AggregateSignature::from_signature(&sig);
1653 for s in sigs.iter().skip(1) {
1654 sig = if sigs_groupcheck {
1655 Signature::sig_validate(s, false)?
1656 } else {
1657 Signature::from_bytes(s)?
1658 };
1659 unsafe {
1660 $sig_add_or_dbl_aff(
1661 &mut agg_sig.point,
1662 &agg_sig.point,
1663 &sig.point,
1664 );
1665 }
1666 }
1667 Ok(agg_sig)
1668 }
1669
1670 pub fn add_aggregate(&mut self, agg_sig: &AggregateSignature) {
1671 unsafe {
1672 $sig_add_or_dbl(
1673 &mut self.point,
1674 &self.point,
1675 &agg_sig.point,
1676 );
1677 }
1678 }
1679
1680 pub fn add_signature(
1681 &mut self,
1682 sig: &Signature,
1683 sig_groupcheck: bool,
1684 ) -> Result<(), BLST_ERROR> {
1685 if sig_groupcheck {
1686 sig.validate(false)?;
1687 }
1688 unsafe {
1689 $sig_add_or_dbl_aff(
1690 &mut self.point,
1691 &self.point,
1692 &sig.point,
1693 );
1694 }
1695 Ok(())
1696 }
1697
1698 pub fn subgroup_check(&self) -> bool {
1699 unsafe { $sig_aggr_in_group(&self.point) }
1700 }
1701 }
1702
1703 impl From<AggregateSignature> for $sig {
1704 fn from(sig: AggregateSignature) -> Self {
1705 sig.point
1706 }
1707 }
1708
1709 impl<'a> From<&'a AggregateSignature> for &'a $sig {
1710 fn from(sig: &'a AggregateSignature) -> Self {
1711 &sig.point
1712 }
1713 }
1714
1715 impl From<$sig> for AggregateSignature {
1716 fn from(point: $sig) -> Self {
1717 Self { point }
1718 }
1719 }
1720
1721 impl MultiPoint for [PublicKey] {
1722 type Output = AggregatePublicKey;
1723
1724 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output {
1725 Self::Output {
1726 point: unsafe { transmute::<&[_], &[$pk_aff]>(self) }
1727 .mult(scalars, nbits),
1728 }
1729 }
1730
1731 fn add(&self) -> Self::Output {
1732 Self::Output {
1733 point: unsafe { transmute::<&[_], &[$pk_aff]>(self) }
1734 .add(),
1735 }
1736 }
1737
1738 fn validate(&self) -> Result<(), BLST_ERROR> {
1739 unsafe { transmute::<&[_], &[$pk_aff]>(self) }.validate()
1740 }
1741 }
1742
1743 impl MultiPoint for [Signature] {
1744 type Output = AggregateSignature;
1745
1746 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output {
1747 Self::Output {
1748 point: unsafe { transmute::<&[_], &[$sig_aff]>(self) }
1749 .mult(scalars, nbits),
1750 }
1751 }
1752
1753 fn add(&self) -> Self::Output {
1754 Self::Output {
1755 point: unsafe { transmute::<&[_], &[$sig_aff]>(self) }
1756 .add(),
1757 }
1758 }
1759
1760 fn validate(&self) -> Result<(), BLST_ERROR> {
1761 unsafe { transmute::<&[_], &[$sig_aff]>(self) }.validate()
1762 }
1763 }
1764
1765 #[cfg(test)]
1766 mod tests {
1767 use super::*;
1768 use rand_core::{RngCore, SeedableRng};
1769 use rand_chacha::ChaCha20Rng;
1770
1771 pub fn gen_random_key(
1773 rng: &mut rand_chacha::ChaCha20Rng,
1774 ) -> SecretKey {
1775 let mut ikm = [0u8; 32];
1776 rng.fill_bytes(&mut ikm);
1777
1778 let mut sk = <blst_scalar>::default();
1779 unsafe {
1780 blst_keygen(&mut sk, ikm.as_ptr(), 32, ptr::null(), 0);
1781 }
1782 SecretKey { value: sk }
1783 }
1784
1785 #[test]
1786 fn test_sign_n_verify() {
1787 let ikm: [u8; 32] = [
1788 0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a, 0x08, 0x3a,
1789 0x91, 0x0c, 0x8b, 0x72, 0x85, 0x91, 0x46, 0x4c, 0xca, 0x56,
1790 0x60, 0x5b, 0xb0, 0x56, 0xed, 0xfe, 0x2b, 0x60, 0xa6, 0x3c,
1791 0x48, 0x99,
1792 ];
1793
1794 let sk = SecretKey::key_gen(&ikm, &[]).unwrap();
1795 let pk = sk.sk_to_pk();
1796
1797 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1798 let msg = b"hello foo";
1799 let sig = sk.sign(msg, dst, &[]);
1800
1801 let err = sig.verify(true, msg, dst, &[], &pk, true);
1802 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
1803 }
1804
1805 #[test]
1806 fn test_aggregate() {
1807 let num_msgs = 10;
1808 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1809
1810 let seed = [0u8; 32];
1811 let mut rng = ChaCha20Rng::from_seed(seed);
1812
1813 let sks: Vec<_> =
1814 (0..num_msgs).map(|_| gen_random_key(&mut rng)).collect();
1815 let pks =
1816 sks.iter().map(|sk| sk.sk_to_pk()).collect::<Vec<_>>();
1817 let pks_refs: Vec<&PublicKey> =
1818 pks.iter().map(|pk| pk).collect();
1819 let pks_rev: Vec<&PublicKey> =
1820 pks.iter().rev().map(|pk| pk).collect();
1821
1822 let pk_comp = pks[0].compress();
1823 let pk_uncomp = PublicKey::uncompress(&pk_comp);
1824 assert_eq!(pk_uncomp.is_ok(), true);
1825
1826 let mut msgs: Vec<Vec<u8>> = vec![vec![]; num_msgs];
1827 for i in 0..num_msgs {
1828 let msg_len = (rng.next_u64() & 0x3F) + 1;
1829 msgs[i] = vec![0u8; msg_len as usize];
1830 rng.fill_bytes(&mut msgs[i]);
1831 }
1832
1833 let msgs_refs: Vec<&[u8]> =
1834 msgs.iter().map(|m| m.as_slice()).collect();
1835
1836 let sigs = sks
1837 .iter()
1838 .zip(msgs.iter())
1839 .map(|(sk, m)| (sk.sign(m, dst, &[])))
1840 .collect::<Vec<Signature>>();
1841
1842 let mut errs = sigs
1843 .iter()
1844 .zip(msgs.iter())
1845 .zip(pks.iter())
1846 .map(|((s, m), pk)| (s.verify(true, m, dst, &[], pk, true)))
1847 .collect::<Vec<BLST_ERROR>>();
1848 assert_eq!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_msgs]);
1849
1850 errs = sigs
1852 .iter()
1853 .zip(msgs.iter())
1854 .zip(pks.iter().rev())
1855 .map(|((s, m), pk)| (s.verify(true, m, dst, &[], pk, true)))
1856 .collect::<Vec<BLST_ERROR>>();
1857 assert_ne!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_msgs]);
1858
1859 let sig_refs =
1860 sigs.iter().map(|s| s).collect::<Vec<&Signature>>();
1861 let agg = match AggregateSignature::aggregate(&sig_refs, true) {
1862 Ok(agg) => agg,
1863 Err(err) => panic!("aggregate failure: {:?}", err),
1864 };
1865
1866 let agg_sig = agg.to_signature();
1867 let mut result = agg_sig
1868 .aggregate_verify(false, &msgs_refs, dst, &pks_refs, false);
1869 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1870
1871 result = agg_sig
1873 .aggregate_verify(false, &msgs_refs, dst, &pks_rev, false);
1874 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1875 }
1876
1877 #[test]
1878 fn test_multiple_agg_sigs() {
1879 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1880 let num_pks_per_sig = 10;
1881 let num_sigs = 10;
1882
1883 let seed = [0u8; 32];
1884 let mut rng = ChaCha20Rng::from_seed(seed);
1885
1886 let mut msgs: Vec<Vec<u8>> = vec![vec![]; num_sigs];
1887 let mut sigs: Vec<Signature> = Vec::with_capacity(num_sigs);
1888 let mut pks: Vec<PublicKey> = Vec::with_capacity(num_sigs);
1889 let mut rands: Vec<blst_scalar> = Vec::with_capacity(num_sigs);
1890 for i in 0..num_sigs {
1891 let sks_i: Vec<_> = (0..num_pks_per_sig)
1893 .map(|_| gen_random_key(&mut rng))
1894 .collect();
1895
1896 let pks_i = sks_i
1897 .iter()
1898 .map(|sk| sk.sk_to_pk())
1899 .collect::<Vec<_>>();
1900 let pks_refs_i: Vec<&PublicKey> =
1901 pks_i.iter().map(|pk| pk).collect();
1902
1903 let msg_len = (rng.next_u64() & 0x3F) + 1;
1905 msgs[i] = vec![0u8; msg_len as usize];
1906 rng.fill_bytes(&mut msgs[i]);
1907
1908 let sigs_i = sks_i
1910 .iter()
1911 .map(|sk| sk.sign(&msgs[i], dst, &[]))
1912 .collect::<Vec<Signature>>();
1913
1914 let errs = sigs_i
1916 .iter()
1917 .zip(pks_i.iter())
1918 .map(|(s, pk)| {
1919 (s.verify(true, &msgs[i], dst, &[], pk, true))
1920 })
1921 .collect::<Vec<BLST_ERROR>>();
1922 assert_eq!(
1923 errs,
1924 vec![BLST_ERROR::BLST_SUCCESS; num_pks_per_sig]
1925 );
1926
1927 let sig_refs_i =
1928 sigs_i.iter().map(|s| s).collect::<Vec<&Signature>>();
1929 let agg_i =
1930 match AggregateSignature::aggregate(&sig_refs_i, false)
1931 {
1932 Ok(agg_i) => agg_i,
1933 Err(err) => panic!("aggregate failure: {:?}", err),
1934 };
1935
1936 sigs.push(agg_i.to_signature());
1938 let mut result = sigs[i].fast_aggregate_verify(
1939 false,
1940 &msgs[i],
1941 dst,
1942 &pks_refs_i,
1943 );
1944 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1945
1946 if i != 0 {
1948 result = sigs[i - 1].fast_aggregate_verify(
1949 false,
1950 &msgs[i],
1951 dst,
1952 &pks_refs_i,
1953 );
1954 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1955 }
1956
1957 let agg_pk_i =
1959 match AggregatePublicKey::aggregate(&pks_refs_i, false)
1960 {
1961 Ok(agg_pk_i) => agg_pk_i,
1962 Err(err) => panic!("aggregate failure: {:?}", err),
1963 };
1964 pks.push(agg_pk_i.to_public_key());
1965
1966 result = sigs[i].fast_aggregate_verify_pre_aggregated(
1968 false, &msgs[i], dst, &pks[i],
1969 );
1970 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1971
1972 if i != 0 {
1974 result = sigs[i - 1]
1975 .fast_aggregate_verify_pre_aggregated(
1976 false, &msgs[i], dst, &pks[i],
1977 );
1978 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1979 }
1980
1981 let mut vals = [0u64; 4];
1983 vals[0] = rng.next_u64();
1984 while vals[0] == 0 {
1985 vals[0] = rng.next_u64();
1987 }
1988 let mut rand_i = MaybeUninit::<blst_scalar>::uninit();
1989 unsafe {
1990 blst_scalar_from_uint64(
1991 rand_i.as_mut_ptr(),
1992 vals.as_ptr(),
1993 );
1994 rands.push(rand_i.assume_init());
1995 }
1996 }
1997
1998 let msgs_refs: Vec<&[u8]> =
1999 msgs.iter().map(|m| m.as_slice()).collect();
2000 let sig_refs =
2001 sigs.iter().map(|s| s).collect::<Vec<&Signature>>();
2002 let pks_refs: Vec<&PublicKey> =
2003 pks.iter().map(|pk| pk).collect();
2004
2005 let msgs_rev: Vec<&[u8]> =
2006 msgs.iter().rev().map(|m| m.as_slice()).collect();
2007 let sig_rev =
2008 sigs.iter().rev().map(|s| s).collect::<Vec<&Signature>>();
2009 let pks_rev: Vec<&PublicKey> =
2010 pks.iter().rev().map(|pk| pk).collect();
2011
2012 let mut result =
2013 Signature::verify_multiple_aggregate_signatures(
2014 &msgs_refs, dst, &pks_refs, false, &sig_refs, true,
2015 &rands, 64,
2016 );
2017 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
2018
2019 result = Signature::verify_multiple_aggregate_signatures(
2021 &msgs_rev, dst, &pks_refs, false, &sig_refs, true, &rands,
2022 64,
2023 );
2024 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
2025
2026 result = Signature::verify_multiple_aggregate_signatures(
2027 &msgs_refs, dst, &pks_rev, false, &sig_refs, true, &rands,
2028 64,
2029 );
2030 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
2031
2032 result = Signature::verify_multiple_aggregate_signatures(
2033 &msgs_refs, dst, &pks_refs, false, &sig_rev, true, &rands,
2034 64,
2035 );
2036 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
2037 }
2038
2039 #[test]
2040 fn test_serialization() {
2041 let seed = [0u8; 32];
2042 let mut rng = ChaCha20Rng::from_seed(seed);
2043
2044 let sk = gen_random_key(&mut rng);
2045 let sk2 = gen_random_key(&mut rng);
2046
2047 let pk = sk.sk_to_pk();
2048 let pk_comp = pk.compress();
2049 let pk_ser = pk.serialize();
2050
2051 let pk_uncomp = PublicKey::uncompress(&pk_comp);
2052 assert_eq!(pk_uncomp.is_ok(), true);
2053 assert_eq!(pk_uncomp.unwrap(), pk);
2054
2055 let pk_deser = PublicKey::deserialize(&pk_ser);
2056 assert_eq!(pk_deser.is_ok(), true);
2057 assert_eq!(pk_deser.unwrap(), pk);
2058
2059 let pk2 = sk2.sk_to_pk();
2060 let pk_comp2 = pk2.compress();
2061 let pk_ser2 = pk2.serialize();
2062
2063 let pk_uncomp2 = PublicKey::uncompress(&pk_comp2);
2064 assert_eq!(pk_uncomp2.is_ok(), true);
2065 assert_eq!(pk_uncomp2.unwrap(), pk2);
2066
2067 let pk_deser2 = PublicKey::deserialize(&pk_ser2);
2068 assert_eq!(pk_deser2.is_ok(), true);
2069 assert_eq!(pk_deser2.unwrap(), pk2);
2070
2071 assert_ne!(pk, pk2);
2072 assert_ne!(pk_uncomp.unwrap(), pk2);
2073 assert_ne!(pk_deser.unwrap(), pk2);
2074 assert_ne!(pk_uncomp2.unwrap(), pk);
2075 assert_ne!(pk_deser2.unwrap(), pk);
2076 }
2077
2078 #[cfg(feature = "serde")]
2079 #[test]
2080 fn test_serde() {
2081 let seed = [0u8; 32];
2082 let mut rng = ChaCha20Rng::from_seed(seed);
2083
2084 let sk = gen_random_key(&mut rng);
2086 let pk = sk.sk_to_pk();
2087 let sig = sk.sign(b"asdf", b"qwer", b"zxcv");
2088 assert_eq!(
2089 sig.verify(true, b"asdf", b"qwer", b"zxcv", &pk, true),
2090 BLST_ERROR::BLST_SUCCESS
2091 );
2092
2093 let pk_ser =
2095 rmp_serde::encode::to_vec_named(&pk).expect("ser pk");
2096 let sig_ser =
2097 rmp_serde::encode::to_vec_named(&sig).expect("ser sig");
2098 let pk_des: PublicKey =
2099 rmp_serde::decode::from_slice(&pk_ser).expect("des pk");
2100 let sig_des: Signature =
2101 rmp_serde::decode::from_slice(&sig_ser).expect("des sig");
2102
2103 assert_eq!(pk, pk_des);
2105 assert_eq!(sig, sig_des);
2106 assert_eq!(
2107 sig.verify(true, b"asdf", b"qwer", b"zxcv", &pk_des, true),
2108 BLST_ERROR::BLST_SUCCESS
2109 );
2110 assert_eq!(
2111 sig_des.verify(true, b"asdf", b"qwer", b"zxcv", &pk, true),
2112 BLST_ERROR::BLST_SUCCESS
2113 );
2114 assert_eq!(sk.sign(b"asdf", b"qwer", b"zxcv"), sig_des);
2115
2116 #[cfg(feature = "serde-secret")]
2117 if true {
2118 let sk_ser =
2119 rmp_serde::encode::to_vec_named(&sk).expect("ser sk");
2120 let sk_des: SecretKey =
2121 rmp_serde::decode::from_slice(&sk_ser).expect("des sk");
2122 assert_eq!(sk_des.sign(b"asdf", b"qwer", b"zxcv"), sig);
2125 }
2126 }
2127
2128 #[test]
2129 fn test_multi_point() {
2130 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
2131 let num_pks = 13;
2132
2133 let seed = [0u8; 32];
2134 let mut rng = ChaCha20Rng::from_seed(seed);
2135
2136 let sks: Vec<_> =
2138 (0..num_pks).map(|_| gen_random_key(&mut rng)).collect();
2139
2140 let pks =
2141 sks.iter().map(|sk| sk.sk_to_pk()).collect::<Vec<_>>();
2142 let pks_refs: Vec<&PublicKey> =
2143 pks.iter().map(|pk| pk).collect();
2144
2145 let msg_len = (rng.next_u64() & 0x3F) + 1;
2147 let mut msg = vec![0u8; msg_len as usize];
2148 rng.fill_bytes(&mut msg);
2149
2150 let sigs = sks
2152 .iter()
2153 .map(|sk| sk.sign(&msg, dst, &[]))
2154 .collect::<Vec<Signature>>();
2155 let sigs_refs: Vec<&Signature> =
2156 sigs.iter().map(|s| s).collect();
2157
2158 let mut rands: Vec<u8> = Vec::with_capacity(8 * num_pks);
2160 for _ in 0..num_pks {
2161 let mut r = rng.next_u64();
2162 while r == 0 {
2163 r = rng.next_u64();
2165 }
2166 rands.extend_from_slice(&r.to_le_bytes());
2167 }
2168
2169 let errs = sigs
2171 .iter()
2172 .zip(pks.iter())
2173 .map(|(s, pk)| (s.verify(true, &msg, dst, &[], pk, true)))
2174 .collect::<Vec<BLST_ERROR>>();
2175 assert_eq!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_pks]);
2176
2177 let agg_pk = AggregatePublicKey::aggregate(&pks_refs, false)
2179 .unwrap()
2180 .to_public_key();
2181 let agg_sig = AggregateSignature::aggregate(&sigs_refs, false)
2182 .unwrap()
2183 .to_signature();
2184 let err = agg_sig.verify(true, &msg, dst, &[], &agg_pk, true);
2185 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
2186
2187 let agg_pk = pks.add().to_public_key();
2189 let agg_sig = sigs.add().to_signature();
2190 let err = agg_sig.verify(true, &msg, dst, &[], &agg_pk, true);
2191 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
2192
2193 let agg_pk = pks.mult(&rands, 64).to_public_key();
2195 let agg_sig = sigs.mult(&rands, 64).to_signature();
2196 let err = agg_sig.verify(true, &msg, dst, &[], &agg_pk, true);
2197 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
2198 }
2199 }
2200 };
2201}
2202
2203pub mod min_pk {
2204 use super::*;
2205
2206 sig_variant_impl!(
2207 "MinPk",
2208 blst_p1,
2209 blst_p1_affine,
2210 blst_p2,
2211 blst_p2_affine,
2212 blst_sk_to_pk2_in_g1,
2213 true,
2214 blst_hash_to_g2,
2215 blst_sign_pk2_in_g1,
2216 blst_p1_affine_is_equal,
2217 blst_p2_affine_is_equal,
2218 blst_core_verify_pk_in_g1,
2219 blst_p1_affine_in_g1,
2220 blst_p1_to_affine,
2221 blst_p1_from_affine,
2222 blst_p1_affine_serialize,
2223 blst_p1_affine_compress,
2224 blst_p1_deserialize,
2225 blst_p1_uncompress,
2226 48,
2227 96,
2228 blst_p2_affine_in_g2,
2229 blst_p2_to_affine,
2230 blst_p2_from_affine,
2231 blst_p2_affine_serialize,
2232 blst_p2_affine_compress,
2233 blst_p2_deserialize,
2234 blst_p2_uncompress,
2235 96,
2236 192,
2237 blst_p1_add_or_double,
2238 blst_p1_add_or_double_affine,
2239 blst_p1_cneg,
2240 blst_p2_add_or_double,
2241 blst_p2_add_or_double_affine,
2242 blst_p1_affine_is_inf,
2243 blst_p2_affine_is_inf,
2244 blst_p2_in_g2,
2245 );
2246}
2247
2248pub mod min_sig {
2249 use super::*;
2250
2251 sig_variant_impl!(
2252 "MinSig",
2253 blst_p2,
2254 blst_p2_affine,
2255 blst_p1,
2256 blst_p1_affine,
2257 blst_sk_to_pk2_in_g2,
2258 true,
2259 blst_hash_to_g1,
2260 blst_sign_pk2_in_g2,
2261 blst_p2_affine_is_equal,
2262 blst_p1_affine_is_equal,
2263 blst_core_verify_pk_in_g2,
2264 blst_p2_affine_in_g2,
2265 blst_p2_to_affine,
2266 blst_p2_from_affine,
2267 blst_p2_affine_serialize,
2268 blst_p2_affine_compress,
2269 blst_p2_deserialize,
2270 blst_p2_uncompress,
2271 96,
2272 192,
2273 blst_p1_affine_in_g1,
2274 blst_p1_to_affine,
2275 blst_p1_from_affine,
2276 blst_p1_affine_serialize,
2277 blst_p1_affine_compress,
2278 blst_p1_deserialize,
2279 blst_p1_uncompress,
2280 48,
2281 96,
2282 blst_p2_add_or_double,
2283 blst_p2_add_or_double_affine,
2284 blst_p2_cneg,
2285 blst_p1_add_or_double,
2286 blst_p1_add_or_double_affine,
2287 blst_p2_affine_is_inf,
2288 blst_p1_affine_is_inf,
2289 blst_p1_in_g1,
2290 );
2291}
2292
2293pub trait MultiPoint {
2294 type Output;
2295
2296 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output;
2297 fn add(&self) -> Self::Output;
2298 fn validate(&self) -> Result<(), BLST_ERROR> {
2299 Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP)
2300 }
2301}
2302
2303#[cfg(feature = "std")]
2304include!("pippenger.rs");
2305
2306#[cfg(not(feature = "std"))]
2307include!("pippenger-no_std.rs");
2308
2309#[cfg(test)]
2310mod fp12_test {
2311 use super::*;
2312 use rand_core::{RngCore, SeedableRng};
2313 use rand_chacha::ChaCha20Rng;
2314
2315 #[test]
2316 fn miller_loop_n() {
2317 const npoints: usize = 97;
2318 const nbits: usize = 64;
2319 const nbytes: usize = (nbits + 7) / 8;
2320
2321 let mut scalars = Box::new([0u8; nbytes * npoints]);
2322 ChaCha20Rng::from_entropy().fill_bytes(scalars.as_mut());
2323
2324 let mut p1s: Vec<blst_p1> = Vec::with_capacity(npoints);
2325 let mut p2s: Vec<blst_p2> = Vec::with_capacity(npoints);
2326
2327 unsafe {
2328 p1s.set_len(npoints);
2329 p2s.set_len(npoints);
2330
2331 for i in 0..npoints {
2332 blst_p1_mult(
2333 &mut p1s[i],
2334 blst_p1_generator(),
2335 &scalars[i * nbytes],
2336 32,
2337 );
2338 blst_p2_mult(
2339 &mut p2s[i],
2340 blst_p2_generator(),
2341 &scalars[i * nbytes + 4],
2342 32,
2343 );
2344 }
2345 }
2346
2347 let ps = p1_affines::from(&p1s);
2348 let qs = p2_affines::from(&p2s);
2349
2350 let mut naive = blst_fp12::default();
2351 for i in 0..npoints {
2352 naive *= blst_fp12::miller_loop(&qs[i], &ps[i]);
2353 }
2354
2355 assert_eq!(
2356 naive,
2357 blst_fp12::miller_loop_n(qs.as_slice(), ps.as_slice())
2358 );
2359 }
2360}
2361
2362#[cfg(test)]
2363mod sk_test {
2364 use super::*;
2365 use rand_core::{RngCore, SeedableRng};
2366 use rand_chacha::ChaCha20Rng;
2367
2368 #[test]
2369 fn inverse() {
2370 let mut bytes = [0u8; 64];
2371 ChaCha20Rng::from_entropy().fill_bytes(bytes.as_mut());
2372
2373 let mut sk = blst_scalar::default();
2374 let mut p1 = blst_p1::default();
2375 let mut p2 = blst_p2::default();
2376
2377 unsafe {
2378 blst_scalar_from_be_bytes(&mut sk, bytes.as_ptr(), bytes.len());
2379
2380 blst_p1_mult(&mut p1, blst_p1_generator(), sk.b.as_ptr(), 255);
2381 blst_sk_inverse(&mut sk, &sk);
2382 blst_p1_mult(&mut p1, &p1, sk.b.as_ptr(), 255);
2383
2384 blst_p2_mult(&mut p2, blst_p2_generator(), sk.b.as_ptr(), 255);
2385 blst_sk_inverse(&mut sk, &sk);
2386 blst_p2_mult(&mut p2, &p2, sk.b.as_ptr(), 255);
2387 }
2388
2389 assert_eq!(p1, unsafe { *blst_p1_generator() });
2390 assert_eq!(p2, unsafe { *blst_p2_generator() });
2391 }
2392}