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