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::sync_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 counter = Arc::new(AtomicUsize::new(0));
194 let stride = core::cmp::min((n_elems + n_workers - 1) / n_workers, 16);
195 n_workers = core::cmp::min((n_elems + stride - 1) / stride, n_workers);
196 let (tx, rx) = sync_channel(n_workers);
197 for _ in 0..n_workers {
198 let tx = tx.clone();
199 let counter = counter.clone();
200
201 pool.joined_execute(move || {
202 let mut acc = blst_fp12::default();
203 let mut tmp = MaybeUninit::<blst_fp12>::uninit();
204 let mut qs: [*const _; 2] = [ptr::null(), ptr::null()];
205 let mut ps: [*const _; 2] = [ptr::null(), ptr::null()];
206
207 loop {
208 let work = counter.fetch_add(stride, Ordering::Relaxed);
209 if work >= n_elems {
210 break;
211 }
212 let n = core::cmp::min(n_elems - work, stride);
213 qs[0] = &q[work];
214 ps[0] = &p[work];
215 unsafe {
216 blst_miller_loop_n(tmp.as_mut_ptr(), &qs[0], &ps[0], n);
217 acc *= tmp.assume_init();
218 }
219 }
220
221 tx.send(acc).expect("disaster");
222 });
223 }
224
225 let mut acc = rx.recv().unwrap();
226 for _ in 1..n_workers {
227 acc *= rx.recv().unwrap();
228 }
229
230 acc
231 }
232
233 pub fn final_exp(&self) -> Self {
234 let mut out = MaybeUninit::<blst_fp12>::uninit();
235 unsafe {
236 blst_final_exp(out.as_mut_ptr(), self);
237 out.assume_init()
238 }
239 }
240
241 pub fn in_group(&self) -> bool {
242 unsafe { blst_fp12_in_group(self) }
243 }
244
245 pub fn finalverify(a: &Self, b: &Self) -> bool {
246 unsafe { blst_fp12_finalverify(a, b) }
247 }
248
249 pub fn to_bendian(&self) -> [u8; 48 * 12] {
250 let mut out = MaybeUninit::<[u8; 48 * 12]>::uninit();
251 unsafe {
252 blst_bendian_from_fp12(out.as_mut_ptr() as *mut u8, self);
253 out.assume_init()
254 }
255 }
256}
257
258impl blst_scalar {
259 pub fn hash_to(msg: &[u8], dst: &[u8]) -> Option<Self> {
260 unsafe {
261 let mut out = <Self>::default();
262 let mut elem = [0u8; 48];
263 blst_expand_message_xmd(
264 elem.as_mut_ptr(),
265 elem.len(),
266 msg.as_ptr(),
267 msg.len(),
268 dst.as_ptr(),
269 dst.len(),
270 );
271 if blst_scalar_from_be_bytes(&mut out, elem.as_ptr(), elem.len()) {
272 Some(out)
273 } else {
274 None
275 }
276 }
277 }
278}
279
280#[derive(Debug)]
281pub struct Pairing {
282 v: Box<[u64]>,
283}
284
285impl Pairing {
286 pub fn new(hash_or_encode: bool, dst: &[u8]) -> Self {
287 let v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
288 let mut obj = Self {
289 v: v.into_boxed_slice(),
290 };
291 obj.init(hash_or_encode, dst);
292 obj
293 }
294
295 pub fn init(&mut self, hash_or_encode: bool, dst: &[u8]) {
296 unsafe {
297 blst_pairing_init(
298 self.ctx(),
299 hash_or_encode,
300 dst.as_ptr(),
301 dst.len(),
302 )
303 }
304 }
305 fn ctx(&mut self) -> *mut blst_pairing {
306 self.v.as_mut_ptr() as *mut blst_pairing
307 }
308 fn const_ctx(&self) -> *const blst_pairing {
309 self.v.as_ptr() as *const blst_pairing
310 }
311
312 pub fn aggregate(
313 &mut self,
314 pk: &dyn Any,
315 pk_validate: bool,
316 sig: &dyn Any,
317 sig_groupcheck: bool,
318 msg: &[u8],
319 aug: &[u8],
320 ) -> BLST_ERROR {
321 if pk.is::<blst_p1_affine>() {
322 unsafe {
323 blst_pairing_chk_n_aggr_pk_in_g1(
324 self.ctx(),
325 match pk.downcast_ref::<blst_p1_affine>() {
326 Some(pk) => pk,
327 None => ptr::null(),
328 },
329 pk_validate,
330 match sig.downcast_ref::<blst_p2_affine>() {
331 Some(sig) => sig,
332 None => ptr::null(),
333 },
334 sig_groupcheck,
335 msg.as_ptr(),
336 msg.len(),
337 aug.as_ptr(),
338 aug.len(),
339 )
340 }
341 } else if pk.is::<blst_p2_affine>() {
342 unsafe {
343 blst_pairing_chk_n_aggr_pk_in_g2(
344 self.ctx(),
345 match pk.downcast_ref::<blst_p2_affine>() {
346 Some(pk) => pk,
347 None => ptr::null(),
348 },
349 pk_validate,
350 match sig.downcast_ref::<blst_p1_affine>() {
351 Some(sig) => sig,
352 None => ptr::null(),
353 },
354 sig_groupcheck,
355 msg.as_ptr(),
356 msg.len(),
357 aug.as_ptr(),
358 aug.len(),
359 )
360 }
361 } else {
362 panic!("whaaaa?")
363 }
364 }
365
366 #[allow(clippy::too_many_arguments)]
367 pub fn mul_n_aggregate(
368 &mut self,
369 pk: &dyn Any,
370 pk_validate: bool,
371 sig: &dyn Any,
372 sig_groupcheck: bool,
373 scalar: &[u8],
374 nbits: usize,
375 msg: &[u8],
376 aug: &[u8],
377 ) -> BLST_ERROR {
378 if pk.is::<blst_p1_affine>() {
379 unsafe {
380 blst_pairing_chk_n_mul_n_aggr_pk_in_g1(
381 self.ctx(),
382 match pk.downcast_ref::<blst_p1_affine>() {
383 Some(pk) => pk,
384 None => ptr::null(),
385 },
386 pk_validate,
387 match sig.downcast_ref::<blst_p2_affine>() {
388 Some(sig) => sig,
389 None => ptr::null(),
390 },
391 sig_groupcheck,
392 scalar.as_ptr(),
393 nbits,
394 msg.as_ptr(),
395 msg.len(),
396 aug.as_ptr(),
397 aug.len(),
398 )
399 }
400 } else if pk.is::<blst_p2_affine>() {
401 unsafe {
402 blst_pairing_chk_n_mul_n_aggr_pk_in_g2(
403 self.ctx(),
404 match pk.downcast_ref::<blst_p2_affine>() {
405 Some(pk) => pk,
406 None => ptr::null(),
407 },
408 pk_validate,
409 match sig.downcast_ref::<blst_p1_affine>() {
410 Some(sig) => sig,
411 None => ptr::null(),
412 },
413 sig_groupcheck,
414 scalar.as_ptr(),
415 nbits,
416 msg.as_ptr(),
417 msg.len(),
418 aug.as_ptr(),
419 aug.len(),
420 )
421 }
422 } else {
423 panic!("whaaaa?")
424 }
425 }
426
427 pub fn aggregated(gtsig: &mut blst_fp12, sig: &dyn Any) {
428 if sig.is::<blst_p1_affine>() {
429 unsafe {
430 blst_aggregated_in_g1(
431 gtsig,
432 sig.downcast_ref::<blst_p1_affine>().unwrap(),
433 )
434 }
435 } else if sig.is::<blst_p2_affine>() {
436 unsafe {
437 blst_aggregated_in_g2(
438 gtsig,
439 sig.downcast_ref::<blst_p2_affine>().unwrap(),
440 )
441 }
442 } else {
443 panic!("whaaaa?")
444 }
445 }
446
447 pub fn commit(&mut self) {
448 unsafe { blst_pairing_commit(self.ctx()) }
449 }
450
451 pub fn merge(&mut self, ctx1: &Self) -> BLST_ERROR {
452 unsafe { blst_pairing_merge(self.ctx(), ctx1.const_ctx()) }
453 }
454
455 pub fn finalverify(&self, gtsig: Option<&blst_fp12>) -> bool {
456 unsafe {
457 blst_pairing_finalverify(
458 self.const_ctx(),
459 match gtsig {
460 Some(gtsig) => gtsig,
461 None => ptr::null(),
462 },
463 )
464 }
465 }
466
467 pub fn raw_aggregate(&mut self, q: &blst_p2_affine, p: &blst_p1_affine) {
468 unsafe { blst_pairing_raw_aggregate(self.ctx(), q, p) }
469 }
470
471 pub fn as_fp12(&mut self) -> blst_fp12 {
472 unsafe { *blst_pairing_as_fp12(self.ctx()) }
473 }
474}
475
476pub fn uniq(msgs: &[&[u8]]) -> bool {
477 let n_elems = msgs.len();
478
479 if n_elems == 1 {
480 return true;
481 } else if n_elems == 2 {
482 return msgs[0] != msgs[1];
483 }
484
485 let mut v: Vec<u64> = vec![0; unsafe { blst_uniq_sizeof(n_elems) } / 8];
486 let ctx = v.as_mut_ptr() as *mut blst_uniq;
487
488 unsafe { blst_uniq_init(ctx) };
489
490 for msg in msgs.iter() {
491 if !unsafe { blst_uniq_test(ctx, msg.as_ptr(), msg.len()) } {
492 return false;
493 }
494 }
495
496 true
497}
498
499#[cfg(feature = "std")]
500pub fn print_bytes(bytes: &[u8], name: &str) {
501 print!("{} ", name);
502 for b in bytes.iter() {
503 print!("{:02x}", b);
504 }
505 println!();
506}
507
508macro_rules! sig_variant_impl {
509 (
510 $name:expr,
511 $pk:ty,
512 $pk_aff:ty,
513 $sig:ty,
514 $sig_aff:ty,
515 $sk_to_pk:ident,
516 $hash_or_encode:expr,
517 $hash_or_encode_to:ident,
518 $sign:ident,
519 $pk_eq:ident,
520 $sig_eq:ident,
521 $verify:ident,
522 $pk_in_group:ident,
523 $pk_to_aff:ident,
524 $pk_from_aff:ident,
525 $pk_ser:ident,
526 $pk_comp:ident,
527 $pk_deser:ident,
528 $pk_uncomp:ident,
529 $pk_comp_size:expr,
530 $pk_ser_size:expr,
531 $sig_in_group:ident,
532 $sig_to_aff:ident,
533 $sig_from_aff:ident,
534 $sig_ser:ident,
535 $sig_comp:ident,
536 $sig_deser:ident,
537 $sig_uncomp:ident,
538 $sig_comp_size:expr,
539 $sig_ser_size:expr,
540 $pk_add_or_dbl:ident,
541 $pk_add_or_dbl_aff:ident,
542 $pk_cneg: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 sub_aggregate(&mut self, agg_pk: &AggregatePublicKey) {
1048 unsafe {
1049 let mut tmp = agg_pk.clone();
1050 $pk_cneg(&mut tmp.point, true);
1051 $pk_add_or_dbl(&mut self.point, &self.point, &tmp.point);
1052 }
1053 }
1054
1055 pub fn add_public_key(
1056 &mut self,
1057 pk: &PublicKey,
1058 pk_validate: bool,
1059 ) -> Result<(), BLST_ERROR> {
1060 if pk_validate {
1061 pk.validate()?;
1062 }
1063 unsafe {
1064 $pk_add_or_dbl_aff(&mut self.point, &self.point, &pk.point);
1065 }
1066 Ok(())
1067 }
1068 }
1069
1070 impl From<AggregatePublicKey> for $pk {
1071 fn from(pk: AggregatePublicKey) -> Self {
1072 pk.point
1073 }
1074 }
1075
1076 impl<'a> From<&'a AggregatePublicKey> for &'a $pk {
1077 fn from(pk: &'a AggregatePublicKey) -> Self {
1078 &pk.point
1079 }
1080 }
1081
1082 impl From<$pk> for AggregatePublicKey {
1083 fn from(point: $pk) -> Self {
1084 Self { point }
1085 }
1086 }
1087
1088 #[repr(transparent)]
1089 #[derive(Debug, Clone, Copy)]
1090 pub struct Signature {
1091 point: $sig_aff,
1092 }
1093
1094 impl Signature {
1095 pub fn validate(
1100 &self,
1101 sig_infcheck: bool,
1102 ) -> Result<(), BLST_ERROR> {
1103 unsafe {
1104 if sig_infcheck && $sig_is_inf(&self.point) {
1105 return Err(BLST_ERROR::BLST_PK_IS_INFINITY);
1106 }
1107 if !$sig_in_group(&self.point) {
1108 return Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP);
1109 }
1110 }
1111 Ok(())
1112 }
1113
1114 pub fn sig_validate(
1115 sig: &[u8],
1116 sig_infcheck: bool,
1117 ) -> Result<Self, BLST_ERROR> {
1118 let sig = Signature::from_bytes(sig)?;
1119 sig.validate(sig_infcheck)?;
1120 Ok(sig)
1121 }
1122
1123 pub fn verify(
1124 &self,
1125 sig_groupcheck: bool,
1126 msg: &[u8],
1127 dst: &[u8],
1128 aug: &[u8],
1129 pk: &PublicKey,
1130 pk_validate: bool,
1131 ) -> BLST_ERROR {
1132 let aug_msg = [aug, msg].concat();
1133 self.aggregate_verify(
1134 sig_groupcheck,
1135 &[aug_msg.as_slice()],
1136 dst,
1137 &[pk],
1138 pk_validate,
1139 )
1140 }
1141
1142 #[cfg(not(feature = "std"))]
1143 pub fn aggregate_verify(
1144 &self,
1145 sig_groupcheck: bool,
1146 msgs: &[&[u8]],
1147 dst: &[u8],
1148 pks: &[&PublicKey],
1149 pks_validate: bool,
1150 ) -> BLST_ERROR {
1151 let n_elems = pks.len();
1152 if n_elems == 0 || msgs.len() != n_elems {
1153 return BLST_ERROR::BLST_VERIFY_FAIL;
1154 }
1155
1156 let mut pairing = Pairing::new($hash_or_encode, dst);
1157
1158 let err = pairing.aggregate(
1159 &pks[0].point,
1160 pks_validate,
1161 &self.point,
1162 sig_groupcheck,
1163 &msgs[0],
1164 &[],
1165 );
1166 if err != BLST_ERROR::BLST_SUCCESS {
1167 return err;
1168 }
1169
1170 for i in 1..n_elems {
1171 let err = pairing.aggregate(
1172 &pks[i].point,
1173 pks_validate,
1174 &unsafe { ptr::null::<$sig_aff>().as_ref() },
1175 false,
1176 &msgs[i],
1177 &[],
1178 );
1179 if err != BLST_ERROR::BLST_SUCCESS {
1180 return err;
1181 }
1182 }
1183
1184 pairing.commit();
1185
1186 if pairing.finalverify(None) {
1187 BLST_ERROR::BLST_SUCCESS
1188 } else {
1189 BLST_ERROR::BLST_VERIFY_FAIL
1190 }
1191 }
1192
1193 #[cfg(feature = "std")]
1194 pub fn aggregate_verify(
1195 &self,
1196 sig_groupcheck: bool,
1197 msgs: &[&[u8]],
1198 dst: &[u8],
1199 pks: &[&PublicKey],
1200 pks_validate: bool,
1201 ) -> BLST_ERROR {
1202 let n_elems = pks.len();
1203 if n_elems == 0 || msgs.len() != n_elems {
1204 return BLST_ERROR::BLST_VERIFY_FAIL;
1205 }
1206
1207 let pool = mt::da_pool();
1210 let counter = Arc::new(AtomicUsize::new(0));
1211 let valid = Arc::new(AtomicBool::new(true));
1212 let n_workers = core::cmp::min(pool.max_count(), n_elems);
1213 let (tx, rx) = sync_channel(n_workers);
1214 for _ in 0..n_workers {
1215 let tx = tx.clone();
1216 let counter = counter.clone();
1217 let valid = valid.clone();
1218
1219 pool.joined_execute(move || {
1220 let mut pairing = Pairing::new($hash_or_encode, dst);
1221
1222 while valid.load(Ordering::Relaxed) {
1223 let work = counter.fetch_add(1, Ordering::Relaxed);
1224 if work >= n_elems {
1225 break;
1226 }
1227 if pairing.aggregate(
1228 &pks[work].point,
1229 pks_validate,
1230 &unsafe { ptr::null::<$sig_aff>().as_ref() },
1231 false,
1232 &msgs[work],
1233 &[],
1234 ) != BLST_ERROR::BLST_SUCCESS
1235 {
1236 valid.store(false, Ordering::Relaxed);
1237 break;
1238 }
1239 }
1240 if valid.load(Ordering::Relaxed) {
1241 pairing.commit();
1242 }
1243 tx.send(pairing).expect("disaster");
1244 });
1245 }
1246
1247 if sig_groupcheck && valid.load(Ordering::Relaxed) {
1248 match self.validate(false) {
1249 Err(_err) => valid.store(false, Ordering::Relaxed),
1250 _ => (),
1251 }
1252 }
1253
1254 let mut gtsig = blst_fp12::default();
1255 if valid.load(Ordering::Relaxed) {
1256 Pairing::aggregated(&mut gtsig, &self.point);
1257 }
1258
1259 let mut acc = rx.recv().unwrap();
1260 for _ in 1..n_workers {
1261 acc.merge(&rx.recv().unwrap());
1262 }
1263
1264 if valid.load(Ordering::Relaxed)
1265 && acc.finalverify(Some(>sig))
1266 {
1267 BLST_ERROR::BLST_SUCCESS
1268 } else {
1269 BLST_ERROR::BLST_VERIFY_FAIL
1270 }
1271 }
1272
1273 pub fn fast_aggregate_verify(
1276 &self,
1277 sig_groupcheck: bool,
1278 msg: &[u8],
1279 dst: &[u8],
1280 pks: &[&PublicKey],
1281 ) -> BLST_ERROR {
1282 let agg_pk = match AggregatePublicKey::aggregate(pks, false) {
1283 Ok(agg_sig) => agg_sig,
1284 Err(err) => return err,
1285 };
1286 let pk = agg_pk.to_public_key();
1287 self.aggregate_verify(
1288 sig_groupcheck,
1289 &[msg],
1290 dst,
1291 &[&pk],
1292 false,
1293 )
1294 }
1295
1296 pub fn fast_aggregate_verify_pre_aggregated(
1297 &self,
1298 sig_groupcheck: bool,
1299 msg: &[u8],
1300 dst: &[u8],
1301 pk: &PublicKey,
1302 ) -> BLST_ERROR {
1303 self.aggregate_verify(sig_groupcheck, &[msg], dst, &[pk], false)
1304 }
1305
1306 #[cfg(feature = "std")]
1308 #[allow(clippy::too_many_arguments)]
1309 pub fn verify_multiple_aggregate_signatures(
1310 msgs: &[&[u8]],
1311 dst: &[u8],
1312 pks: &[&PublicKey],
1313 pks_validate: bool,
1314 sigs: &[&Signature],
1315 sigs_groupcheck: bool,
1316 rands: &[blst_scalar],
1317 rand_bits: usize,
1318 ) -> BLST_ERROR {
1319 let n_elems = pks.len();
1320 if n_elems == 0
1321 || msgs.len() != n_elems
1322 || sigs.len() != n_elems
1323 || rands.len() != n_elems
1324 {
1325 return BLST_ERROR::BLST_VERIFY_FAIL;
1326 }
1327
1328 let pool = mt::da_pool();
1331 let counter = Arc::new(AtomicUsize::new(0));
1332 let valid = Arc::new(AtomicBool::new(true));
1333 let n_workers = core::cmp::min(pool.max_count(), n_elems);
1334 let (tx, rx) = sync_channel(n_workers);
1335 for _ in 0..n_workers {
1336 let tx = tx.clone();
1337 let counter = counter.clone();
1338 let valid = valid.clone();
1339
1340 pool.joined_execute(move || {
1341 let mut pairing = Pairing::new($hash_or_encode, dst);
1342
1343 while valid.load(Ordering::Relaxed) {
1346 let work = counter.fetch_add(1, Ordering::Relaxed);
1347 if work >= n_elems {
1348 break;
1349 }
1350
1351 if pairing.mul_n_aggregate(
1352 &pks[work].point,
1353 pks_validate,
1354 &sigs[work].point,
1355 sigs_groupcheck,
1356 &rands[work].b,
1357 rand_bits,
1358 msgs[work],
1359 &[],
1360 ) != BLST_ERROR::BLST_SUCCESS
1361 {
1362 valid.store(false, Ordering::Relaxed);
1363 break;
1364 }
1365 }
1366 if valid.load(Ordering::Relaxed) {
1367 pairing.commit();
1368 }
1369 tx.send(pairing).expect("disaster");
1370 });
1371 }
1372
1373 let mut acc = rx.recv().unwrap();
1374 for _ in 1..n_workers {
1375 acc.merge(&rx.recv().unwrap());
1376 }
1377
1378 if valid.load(Ordering::Relaxed) && acc.finalverify(None) {
1379 BLST_ERROR::BLST_SUCCESS
1380 } else {
1381 BLST_ERROR::BLST_VERIFY_FAIL
1382 }
1383 }
1384
1385 #[cfg(not(feature = "std"))]
1386 #[allow(clippy::too_many_arguments)]
1387 pub fn verify_multiple_aggregate_signatures(
1388 msgs: &[&[u8]],
1389 dst: &[u8],
1390 pks: &[&PublicKey],
1391 pks_validate: bool,
1392 sigs: &[&Signature],
1393 sigs_groupcheck: bool,
1394 rands: &[blst_scalar],
1395 rand_bits: usize,
1396 ) -> BLST_ERROR {
1397 let n_elems = pks.len();
1398 if n_elems == 0
1399 || msgs.len() != n_elems
1400 || sigs.len() != n_elems
1401 || rands.len() != n_elems
1402 {
1403 return BLST_ERROR::BLST_VERIFY_FAIL;
1404 }
1405
1406 let mut pairing = Pairing::new($hash_or_encode, dst);
1409
1410 for i in 0..n_elems {
1411 let err = pairing.mul_n_aggregate(
1412 &pks[i].point,
1413 pks_validate,
1414 &sigs[i].point,
1415 sigs_groupcheck,
1416 &rands[i].b,
1417 rand_bits,
1418 msgs[i],
1419 &[],
1420 );
1421 if err != BLST_ERROR::BLST_SUCCESS {
1422 return err;
1423 }
1424 }
1425
1426 pairing.commit();
1427
1428 if pairing.finalverify(None) {
1429 BLST_ERROR::BLST_SUCCESS
1430 } else {
1431 BLST_ERROR::BLST_VERIFY_FAIL
1432 }
1433 }
1434
1435 pub fn from_aggregate(agg_sig: &AggregateSignature) -> Self {
1436 let mut sig_aff = <$sig_aff>::default();
1437 unsafe {
1438 $sig_to_aff(&mut sig_aff, &agg_sig.point);
1439 }
1440 Self { point: sig_aff }
1441 }
1442
1443 pub fn compress(&self) -> [u8; $sig_comp_size] {
1444 let mut sig_comp = [0; $sig_comp_size];
1445 unsafe {
1446 $sig_comp(sig_comp.as_mut_ptr(), &self.point);
1447 }
1448 sig_comp
1449 }
1450
1451 pub fn serialize(&self) -> [u8; $sig_ser_size] {
1452 let mut sig_out = [0; $sig_ser_size];
1453 unsafe {
1454 $sig_ser(sig_out.as_mut_ptr(), &self.point);
1455 }
1456 sig_out
1457 }
1458
1459 pub fn uncompress(sig_comp: &[u8]) -> Result<Self, BLST_ERROR> {
1460 if sig_comp.len() == $sig_comp_size && (sig_comp[0] & 0x80) != 0
1461 {
1462 let mut sig = <$sig_aff>::default();
1463 let err =
1464 unsafe { $sig_uncomp(&mut sig, sig_comp.as_ptr()) };
1465 if err != BLST_ERROR::BLST_SUCCESS {
1466 return Err(err);
1467 }
1468 Ok(Self { point: sig })
1469 } else {
1470 Err(BLST_ERROR::BLST_BAD_ENCODING)
1471 }
1472 }
1473
1474 pub fn deserialize(sig_in: &[u8]) -> Result<Self, BLST_ERROR> {
1475 if (sig_in.len() == $sig_ser_size && (sig_in[0] & 0x80) == 0)
1476 || (sig_in.len() == $sig_comp_size
1477 && (sig_in[0] & 0x80) != 0)
1478 {
1479 let mut sig = <$sig_aff>::default();
1480 let err = unsafe { $sig_deser(&mut sig, sig_in.as_ptr()) };
1481 if err != BLST_ERROR::BLST_SUCCESS {
1482 return Err(err);
1483 }
1484 Ok(Self { point: sig })
1485 } else {
1486 Err(BLST_ERROR::BLST_BAD_ENCODING)
1487 }
1488 }
1489
1490 pub fn from_bytes(sig_in: &[u8]) -> Result<Self, BLST_ERROR> {
1491 Signature::deserialize(sig_in)
1492 }
1493
1494 pub fn to_bytes(&self) -> [u8; $sig_comp_size] {
1495 self.compress()
1496 }
1497
1498 pub fn subgroup_check(&self) -> bool {
1499 unsafe { $sig_in_group(&self.point) }
1500 }
1501 }
1502
1503 impl Eq for Signature {}
1508
1509 impl PartialEq for Signature {
1510 fn eq(&self, other: &Self) -> bool {
1511 unsafe { $sig_eq(&self.point, &other.point) }
1512 }
1513 }
1514
1515 #[cfg(feature = "serde")]
1516 impl Serialize for Signature {
1517 fn serialize<S: Serializer>(
1518 &self,
1519 ser: S,
1520 ) -> Result<S::Ok, S::Error> {
1521 ser.serialize_bytes(&self.serialize())
1522 }
1523 }
1524
1525 #[cfg(feature = "serde")]
1526 impl<'de> Deserialize<'de> for Signature {
1527 fn deserialize<D: Deserializer<'de>>(
1528 deser: D,
1529 ) -> Result<Self, D::Error> {
1530 let bytes: &[u8] = Deserialize::deserialize(deser)?;
1531 Self::deserialize(&bytes).map_err(|e| {
1532 <D::Error as serde::de::Error>::custom(format!("{:?}", e))
1533 })
1534 }
1535 }
1536
1537 impl From<Signature> for $sig_aff {
1538 fn from(sig: Signature) -> Self {
1539 sig.point
1540 }
1541 }
1542
1543 impl<'a> From<&'a Signature> for &'a $sig_aff {
1544 fn from(sig: &'a Signature) -> Self {
1545 &sig.point
1546 }
1547 }
1548
1549 impl From<$sig_aff> for Signature {
1550 fn from(point: $sig_aff) -> Self {
1551 Self { point }
1552 }
1553 }
1554
1555 #[repr(transparent)]
1556 #[derive(Debug, Clone, Copy)]
1557 pub struct AggregateSignature {
1558 point: $sig,
1559 }
1560
1561 impl AggregateSignature {
1562 pub fn validate(&self) -> Result<(), BLST_ERROR> {
1563 unsafe {
1564 if !$sig_aggr_in_group(&self.point) {
1565 return Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP);
1566 }
1567 }
1568 Ok(())
1569 }
1570
1571 pub fn from_signature(sig: &Signature) -> Self {
1572 let mut agg_sig = <$sig>::default();
1573 unsafe {
1574 $sig_from_aff(&mut agg_sig, &sig.point);
1575 }
1576 Self { point: agg_sig }
1577 }
1578
1579 pub fn to_signature(&self) -> Signature {
1580 let mut sig = <$sig_aff>::default();
1581 unsafe {
1582 $sig_to_aff(&mut sig, &self.point);
1583 }
1584 Signature { point: sig }
1585 }
1586
1587 pub fn aggregate(
1589 sigs: &[&Signature],
1590 sigs_groupcheck: bool,
1591 ) -> Result<Self, BLST_ERROR> {
1592 if sigs.len() == 0 {
1593 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1594 }
1595 if sigs_groupcheck {
1596 sigs[0].validate(false)?;
1600 }
1601 let mut agg_sig = AggregateSignature::from_signature(sigs[0]);
1602 for s in sigs.iter().skip(1) {
1603 if sigs_groupcheck {
1604 s.validate(false)?;
1605 }
1606 unsafe {
1607 $sig_add_or_dbl_aff(
1608 &mut agg_sig.point,
1609 &agg_sig.point,
1610 &s.point,
1611 );
1612 }
1613 }
1614 Ok(agg_sig)
1615 }
1616
1617 pub fn aggregate_with_randomness(
1618 sigs: &[Signature],
1619 randomness: &[u8],
1620 nbits: usize,
1621 sigs_groupcheck: bool,
1622 ) -> Result<Self, BLST_ERROR> {
1623 if sigs.len() == 0 {
1624 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1625 }
1626 if sigs_groupcheck {
1627 sigs.validate()?;
1628 }
1629 Ok(sigs.mult(randomness, nbits))
1630 }
1631
1632 pub fn aggregate_serialized(
1633 sigs: &[&[u8]],
1634 sigs_groupcheck: bool,
1635 ) -> Result<Self, BLST_ERROR> {
1636 if sigs.len() == 0 {
1638 return Err(BLST_ERROR::BLST_AGGR_TYPE_MISMATCH);
1639 }
1640 let mut sig = if sigs_groupcheck {
1641 Signature::sig_validate(sigs[0], false)?
1642 } else {
1643 Signature::from_bytes(sigs[0])?
1644 };
1645 let mut agg_sig = AggregateSignature::from_signature(&sig);
1646 for s in sigs.iter().skip(1) {
1647 sig = if sigs_groupcheck {
1648 Signature::sig_validate(s, false)?
1649 } else {
1650 Signature::from_bytes(s)?
1651 };
1652 unsafe {
1653 $sig_add_or_dbl_aff(
1654 &mut agg_sig.point,
1655 &agg_sig.point,
1656 &sig.point,
1657 );
1658 }
1659 }
1660 Ok(agg_sig)
1661 }
1662
1663 pub fn add_aggregate(&mut self, agg_sig: &AggregateSignature) {
1664 unsafe {
1665 $sig_add_or_dbl(
1666 &mut self.point,
1667 &self.point,
1668 &agg_sig.point,
1669 );
1670 }
1671 }
1672
1673 pub fn add_signature(
1674 &mut self,
1675 sig: &Signature,
1676 sig_groupcheck: bool,
1677 ) -> Result<(), BLST_ERROR> {
1678 if sig_groupcheck {
1679 sig.validate(false)?;
1680 }
1681 unsafe {
1682 $sig_add_or_dbl_aff(
1683 &mut self.point,
1684 &self.point,
1685 &sig.point,
1686 );
1687 }
1688 Ok(())
1689 }
1690
1691 pub fn subgroup_check(&self) -> bool {
1692 unsafe { $sig_aggr_in_group(&self.point) }
1693 }
1694 }
1695
1696 impl From<AggregateSignature> for $sig {
1697 fn from(sig: AggregateSignature) -> Self {
1698 sig.point
1699 }
1700 }
1701
1702 impl<'a> From<&'a AggregateSignature> for &'a $sig {
1703 fn from(sig: &'a AggregateSignature) -> Self {
1704 &sig.point
1705 }
1706 }
1707
1708 impl From<$sig> for AggregateSignature {
1709 fn from(point: $sig) -> Self {
1710 Self { point }
1711 }
1712 }
1713
1714 impl MultiPoint for [PublicKey] {
1715 type Output = AggregatePublicKey;
1716
1717 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output {
1718 Self::Output {
1719 point: unsafe { transmute::<&[_], &[$pk_aff]>(self) }
1720 .mult(scalars, nbits),
1721 }
1722 }
1723
1724 fn add(&self) -> Self::Output {
1725 Self::Output {
1726 point: unsafe { transmute::<&[_], &[$pk_aff]>(self) }
1727 .add(),
1728 }
1729 }
1730
1731 fn validate(&self) -> Result<(), BLST_ERROR> {
1732 unsafe { transmute::<&[_], &[$pk_aff]>(self) }.validate()
1733 }
1734 }
1735
1736 impl MultiPoint for [Signature] {
1737 type Output = AggregateSignature;
1738
1739 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output {
1740 Self::Output {
1741 point: unsafe { transmute::<&[_], &[$sig_aff]>(self) }
1742 .mult(scalars, nbits),
1743 }
1744 }
1745
1746 fn add(&self) -> Self::Output {
1747 Self::Output {
1748 point: unsafe { transmute::<&[_], &[$sig_aff]>(self) }
1749 .add(),
1750 }
1751 }
1752
1753 fn validate(&self) -> Result<(), BLST_ERROR> {
1754 unsafe { transmute::<&[_], &[$sig_aff]>(self) }.validate()
1755 }
1756 }
1757
1758 #[cfg(test)]
1759 mod tests {
1760 use super::*;
1761 use rand::{RngCore, SeedableRng};
1762 use rand_chacha::ChaCha20Rng;
1763
1764 pub fn gen_random_key(
1766 rng: &mut rand_chacha::ChaCha20Rng,
1767 ) -> SecretKey {
1768 let mut ikm = [0u8; 32];
1769 rng.fill_bytes(&mut ikm);
1770
1771 let mut sk = <blst_scalar>::default();
1772 unsafe {
1773 blst_keygen(&mut sk, ikm.as_ptr(), 32, ptr::null(), 0);
1774 }
1775 SecretKey { value: sk }
1776 }
1777
1778 #[test]
1779 fn test_sign_n_verify() {
1780 let ikm: [u8; 32] = [
1781 0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a, 0x08, 0x3a,
1782 0x91, 0x0c, 0x8b, 0x72, 0x85, 0x91, 0x46, 0x4c, 0xca, 0x56,
1783 0x60, 0x5b, 0xb0, 0x56, 0xed, 0xfe, 0x2b, 0x60, 0xa6, 0x3c,
1784 0x48, 0x99,
1785 ];
1786
1787 let sk = SecretKey::key_gen(&ikm, &[]).unwrap();
1788 let pk = sk.sk_to_pk();
1789
1790 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1791 let msg = b"hello foo";
1792 let sig = sk.sign(msg, dst, &[]);
1793
1794 let err = sig.verify(true, msg, dst, &[], &pk, true);
1795 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
1796 }
1797
1798 #[test]
1799 fn test_aggregate() {
1800 let num_msgs = 10;
1801 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1802
1803 let seed = [0u8; 32];
1804 let mut rng = ChaCha20Rng::from_seed(seed);
1805
1806 let sks: Vec<_> =
1807 (0..num_msgs).map(|_| gen_random_key(&mut rng)).collect();
1808 let pks =
1809 sks.iter().map(|sk| sk.sk_to_pk()).collect::<Vec<_>>();
1810 let pks_refs: Vec<&PublicKey> =
1811 pks.iter().map(|pk| pk).collect();
1812 let pks_rev: Vec<&PublicKey> =
1813 pks.iter().rev().map(|pk| pk).collect();
1814
1815 let pk_comp = pks[0].compress();
1816 let pk_uncomp = PublicKey::uncompress(&pk_comp);
1817 assert_eq!(pk_uncomp.is_ok(), true);
1818
1819 let mut msgs: Vec<Vec<u8>> = vec![vec![]; num_msgs];
1820 for i in 0..num_msgs {
1821 let msg_len = (rng.next_u64() & 0x3F) + 1;
1822 msgs[i] = vec![0u8; msg_len as usize];
1823 rng.fill_bytes(&mut msgs[i]);
1824 }
1825
1826 let msgs_refs: Vec<&[u8]> =
1827 msgs.iter().map(|m| m.as_slice()).collect();
1828
1829 let sigs = sks
1830 .iter()
1831 .zip(msgs.iter())
1832 .map(|(sk, m)| (sk.sign(m, dst, &[])))
1833 .collect::<Vec<Signature>>();
1834
1835 let mut errs = sigs
1836 .iter()
1837 .zip(msgs.iter())
1838 .zip(pks.iter())
1839 .map(|((s, m), pk)| (s.verify(true, m, dst, &[], pk, true)))
1840 .collect::<Vec<BLST_ERROR>>();
1841 assert_eq!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_msgs]);
1842
1843 errs = sigs
1845 .iter()
1846 .zip(msgs.iter())
1847 .zip(pks.iter().rev())
1848 .map(|((s, m), pk)| (s.verify(true, m, dst, &[], pk, true)))
1849 .collect::<Vec<BLST_ERROR>>();
1850 assert_ne!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_msgs]);
1851
1852 let sig_refs =
1853 sigs.iter().map(|s| s).collect::<Vec<&Signature>>();
1854 let agg = match AggregateSignature::aggregate(&sig_refs, true) {
1855 Ok(agg) => agg,
1856 Err(err) => panic!("aggregate failure: {:?}", err),
1857 };
1858
1859 let agg_sig = agg.to_signature();
1860 let mut result = agg_sig
1861 .aggregate_verify(false, &msgs_refs, dst, &pks_refs, false);
1862 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1863
1864 result = agg_sig
1866 .aggregate_verify(false, &msgs_refs, dst, &pks_rev, false);
1867 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1868 }
1869
1870 #[test]
1871 fn test_multiple_agg_sigs() {
1872 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1873 let num_pks_per_sig = 10;
1874 let num_sigs = 10;
1875
1876 let seed = [0u8; 32];
1877 let mut rng = ChaCha20Rng::from_seed(seed);
1878
1879 let mut msgs: Vec<Vec<u8>> = vec![vec![]; num_sigs];
1880 let mut sigs: Vec<Signature> = Vec::with_capacity(num_sigs);
1881 let mut pks: Vec<PublicKey> = Vec::with_capacity(num_sigs);
1882 let mut rands: Vec<blst_scalar> = Vec::with_capacity(num_sigs);
1883 for i in 0..num_sigs {
1884 let sks_i: Vec<_> = (0..num_pks_per_sig)
1886 .map(|_| gen_random_key(&mut rng))
1887 .collect();
1888
1889 let pks_i = sks_i
1890 .iter()
1891 .map(|sk| sk.sk_to_pk())
1892 .collect::<Vec<_>>();
1893 let pks_refs_i: Vec<&PublicKey> =
1894 pks_i.iter().map(|pk| pk).collect();
1895
1896 let msg_len = (rng.next_u64() & 0x3F) + 1;
1898 msgs[i] = vec![0u8; msg_len as usize];
1899 rng.fill_bytes(&mut msgs[i]);
1900
1901 let sigs_i = sks_i
1903 .iter()
1904 .map(|sk| sk.sign(&msgs[i], dst, &[]))
1905 .collect::<Vec<Signature>>();
1906
1907 let errs = sigs_i
1909 .iter()
1910 .zip(pks_i.iter())
1911 .map(|(s, pk)| {
1912 (s.verify(true, &msgs[i], dst, &[], pk, true))
1913 })
1914 .collect::<Vec<BLST_ERROR>>();
1915 assert_eq!(
1916 errs,
1917 vec![BLST_ERROR::BLST_SUCCESS; num_pks_per_sig]
1918 );
1919
1920 let sig_refs_i =
1921 sigs_i.iter().map(|s| s).collect::<Vec<&Signature>>();
1922 let agg_i =
1923 match AggregateSignature::aggregate(&sig_refs_i, false)
1924 {
1925 Ok(agg_i) => agg_i,
1926 Err(err) => panic!("aggregate failure: {:?}", err),
1927 };
1928
1929 sigs.push(agg_i.to_signature());
1931 let mut result = sigs[i].fast_aggregate_verify(
1932 false,
1933 &msgs[i],
1934 dst,
1935 &pks_refs_i,
1936 );
1937 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1938
1939 if i != 0 {
1941 result = sigs[i - 1].fast_aggregate_verify(
1942 false,
1943 &msgs[i],
1944 dst,
1945 &pks_refs_i,
1946 );
1947 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1948 }
1949
1950 let agg_pk_i =
1952 match AggregatePublicKey::aggregate(&pks_refs_i, false)
1953 {
1954 Ok(agg_pk_i) => agg_pk_i,
1955 Err(err) => panic!("aggregate failure: {:?}", err),
1956 };
1957 pks.push(agg_pk_i.to_public_key());
1958
1959 result = sigs[i].fast_aggregate_verify_pre_aggregated(
1961 false, &msgs[i], dst, &pks[i],
1962 );
1963 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
1964
1965 if i != 0 {
1967 result = sigs[i - 1]
1968 .fast_aggregate_verify_pre_aggregated(
1969 false, &msgs[i], dst, &pks[i],
1970 );
1971 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
1972 }
1973
1974 let mut vals = [0u64; 4];
1976 vals[0] = rng.next_u64();
1977 while vals[0] == 0 {
1978 vals[0] = rng.next_u64();
1980 }
1981 let mut rand_i = MaybeUninit::<blst_scalar>::uninit();
1982 unsafe {
1983 blst_scalar_from_uint64(
1984 rand_i.as_mut_ptr(),
1985 vals.as_ptr(),
1986 );
1987 rands.push(rand_i.assume_init());
1988 }
1989 }
1990
1991 let msgs_refs: Vec<&[u8]> =
1992 msgs.iter().map(|m| m.as_slice()).collect();
1993 let sig_refs =
1994 sigs.iter().map(|s| s).collect::<Vec<&Signature>>();
1995 let pks_refs: Vec<&PublicKey> =
1996 pks.iter().map(|pk| pk).collect();
1997
1998 let msgs_rev: Vec<&[u8]> =
1999 msgs.iter().rev().map(|m| m.as_slice()).collect();
2000 let sig_rev =
2001 sigs.iter().rev().map(|s| s).collect::<Vec<&Signature>>();
2002 let pks_rev: Vec<&PublicKey> =
2003 pks.iter().rev().map(|pk| pk).collect();
2004
2005 let mut result =
2006 Signature::verify_multiple_aggregate_signatures(
2007 &msgs_refs, dst, &pks_refs, false, &sig_refs, true,
2008 &rands, 64,
2009 );
2010 assert_eq!(result, BLST_ERROR::BLST_SUCCESS);
2011
2012 result = Signature::verify_multiple_aggregate_signatures(
2014 &msgs_rev, dst, &pks_refs, 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_rev, false, &sig_refs, true, &rands,
2021 64,
2022 );
2023 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
2024
2025 result = Signature::verify_multiple_aggregate_signatures(
2026 &msgs_refs, dst, &pks_refs, false, &sig_rev, true, &rands,
2027 64,
2028 );
2029 assert_ne!(result, BLST_ERROR::BLST_SUCCESS);
2030 }
2031
2032 #[test]
2033 fn test_serialization() {
2034 let seed = [0u8; 32];
2035 let mut rng = ChaCha20Rng::from_seed(seed);
2036
2037 let sk = gen_random_key(&mut rng);
2038 let sk2 = gen_random_key(&mut rng);
2039
2040 let pk = sk.sk_to_pk();
2041 let pk_comp = pk.compress();
2042 let pk_ser = pk.serialize();
2043
2044 let pk_uncomp = PublicKey::uncompress(&pk_comp);
2045 assert_eq!(pk_uncomp.is_ok(), true);
2046 assert_eq!(pk_uncomp.unwrap(), pk);
2047
2048 let pk_deser = PublicKey::deserialize(&pk_ser);
2049 assert_eq!(pk_deser.is_ok(), true);
2050 assert_eq!(pk_deser.unwrap(), pk);
2051
2052 let pk2 = sk2.sk_to_pk();
2053 let pk_comp2 = pk2.compress();
2054 let pk_ser2 = pk2.serialize();
2055
2056 let pk_uncomp2 = PublicKey::uncompress(&pk_comp2);
2057 assert_eq!(pk_uncomp2.is_ok(), true);
2058 assert_eq!(pk_uncomp2.unwrap(), pk2);
2059
2060 let pk_deser2 = PublicKey::deserialize(&pk_ser2);
2061 assert_eq!(pk_deser2.is_ok(), true);
2062 assert_eq!(pk_deser2.unwrap(), pk2);
2063
2064 assert_ne!(pk, pk2);
2065 assert_ne!(pk_uncomp.unwrap(), pk2);
2066 assert_ne!(pk_deser.unwrap(), pk2);
2067 assert_ne!(pk_uncomp2.unwrap(), pk);
2068 assert_ne!(pk_deser2.unwrap(), pk);
2069 }
2070
2071 #[cfg(feature = "serde")]
2072 #[test]
2073 fn test_serde() {
2074 let seed = [0u8; 32];
2075 let mut rng = ChaCha20Rng::from_seed(seed);
2076
2077 let sk = gen_random_key(&mut rng);
2079 let pk = sk.sk_to_pk();
2080 let sig = sk.sign(b"asdf", b"qwer", b"zxcv");
2081 assert_eq!(
2082 sig.verify(true, b"asdf", b"qwer", b"zxcv", &pk, true),
2083 BLST_ERROR::BLST_SUCCESS
2084 );
2085
2086 let pk_ser =
2088 rmp_serde::encode::to_vec_named(&pk).expect("ser pk");
2089 let sig_ser =
2090 rmp_serde::encode::to_vec_named(&sig).expect("ser sig");
2091 let pk_des: PublicKey =
2092 rmp_serde::decode::from_slice(&pk_ser).expect("des pk");
2093 let sig_des: Signature =
2094 rmp_serde::decode::from_slice(&sig_ser).expect("des sig");
2095
2096 assert_eq!(pk, pk_des);
2098 assert_eq!(sig, sig_des);
2099 assert_eq!(
2100 sig.verify(true, b"asdf", b"qwer", b"zxcv", &pk_des, true),
2101 BLST_ERROR::BLST_SUCCESS
2102 );
2103 assert_eq!(
2104 sig_des.verify(true, b"asdf", b"qwer", b"zxcv", &pk, true),
2105 BLST_ERROR::BLST_SUCCESS
2106 );
2107 assert_eq!(sk.sign(b"asdf", b"qwer", b"zxcv"), sig_des);
2108
2109 #[cfg(feature = "serde-secret")]
2110 if true {
2111 let sk_ser =
2112 rmp_serde::encode::to_vec_named(&sk).expect("ser sk");
2113 let sk_des: SecretKey =
2114 rmp_serde::decode::from_slice(&sk_ser).expect("des sk");
2115 assert_eq!(sk_des.sign(b"asdf", b"qwer", b"zxcv"), sig);
2118 }
2119 }
2120
2121 #[test]
2122 fn test_multi_point() {
2123 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
2124 let num_pks = 13;
2125
2126 let seed = [0u8; 32];
2127 let mut rng = ChaCha20Rng::from_seed(seed);
2128
2129 let sks: Vec<_> =
2131 (0..num_pks).map(|_| gen_random_key(&mut rng)).collect();
2132
2133 let pks =
2134 sks.iter().map(|sk| sk.sk_to_pk()).collect::<Vec<_>>();
2135 let pks_refs: Vec<&PublicKey> =
2136 pks.iter().map(|pk| pk).collect();
2137
2138 let msg_len = (rng.next_u64() & 0x3F) + 1;
2140 let mut msg = vec![0u8; msg_len as usize];
2141 rng.fill_bytes(&mut msg);
2142
2143 let sigs = sks
2145 .iter()
2146 .map(|sk| sk.sign(&msg, dst, &[]))
2147 .collect::<Vec<Signature>>();
2148 let sigs_refs: Vec<&Signature> =
2149 sigs.iter().map(|s| s).collect();
2150
2151 let mut rands: Vec<u8> = Vec::with_capacity(8 * num_pks);
2153 for _ in 0..num_pks {
2154 let mut r = rng.next_u64();
2155 while r == 0 {
2156 r = rng.next_u64();
2158 }
2159 rands.extend_from_slice(&r.to_le_bytes());
2160 }
2161
2162 let errs = sigs
2164 .iter()
2165 .zip(pks.iter())
2166 .map(|(s, pk)| (s.verify(true, &msg, dst, &[], pk, true)))
2167 .collect::<Vec<BLST_ERROR>>();
2168 assert_eq!(errs, vec![BLST_ERROR::BLST_SUCCESS; num_pks]);
2169
2170 let agg_pk = AggregatePublicKey::aggregate(&pks_refs, false)
2172 .unwrap()
2173 .to_public_key();
2174 let agg_sig = AggregateSignature::aggregate(&sigs_refs, false)
2175 .unwrap()
2176 .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.add().to_public_key();
2182 let agg_sig = sigs.add().to_signature();
2183 let err = agg_sig.verify(true, &msg, dst, &[], &agg_pk, true);
2184 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
2185
2186 let agg_pk = pks.mult(&rands, 64).to_public_key();
2188 let agg_sig = sigs.mult(&rands, 64).to_signature();
2189 let err = agg_sig.verify(true, &msg, dst, &[], &agg_pk, true);
2190 assert_eq!(err, BLST_ERROR::BLST_SUCCESS);
2191 }
2192 }
2193 };
2194}
2195
2196pub mod min_pk {
2197 use super::*;
2198
2199 sig_variant_impl!(
2200 "MinPk",
2201 blst_p1,
2202 blst_p1_affine,
2203 blst_p2,
2204 blst_p2_affine,
2205 blst_sk_to_pk2_in_g1,
2206 true,
2207 blst_hash_to_g2,
2208 blst_sign_pk2_in_g1,
2209 blst_p1_affine_is_equal,
2210 blst_p2_affine_is_equal,
2211 blst_core_verify_pk_in_g1,
2212 blst_p1_affine_in_g1,
2213 blst_p1_to_affine,
2214 blst_p1_from_affine,
2215 blst_p1_affine_serialize,
2216 blst_p1_affine_compress,
2217 blst_p1_deserialize,
2218 blst_p1_uncompress,
2219 48,
2220 96,
2221 blst_p2_affine_in_g2,
2222 blst_p2_to_affine,
2223 blst_p2_from_affine,
2224 blst_p2_affine_serialize,
2225 blst_p2_affine_compress,
2226 blst_p2_deserialize,
2227 blst_p2_uncompress,
2228 96,
2229 192,
2230 blst_p1_add_or_double,
2231 blst_p1_add_or_double_affine,
2232 blst_p1_cneg,
2233 blst_p2_add_or_double,
2234 blst_p2_add_or_double_affine,
2235 blst_p1_affine_is_inf,
2236 blst_p2_affine_is_inf,
2237 blst_p2_in_g2,
2238 );
2239}
2240
2241pub mod min_sig {
2242 use super::*;
2243
2244 sig_variant_impl!(
2245 "MinSig",
2246 blst_p2,
2247 blst_p2_affine,
2248 blst_p1,
2249 blst_p1_affine,
2250 blst_sk_to_pk2_in_g2,
2251 true,
2252 blst_hash_to_g1,
2253 blst_sign_pk2_in_g2,
2254 blst_p2_affine_is_equal,
2255 blst_p1_affine_is_equal,
2256 blst_core_verify_pk_in_g2,
2257 blst_p2_affine_in_g2,
2258 blst_p2_to_affine,
2259 blst_p2_from_affine,
2260 blst_p2_affine_serialize,
2261 blst_p2_affine_compress,
2262 blst_p2_deserialize,
2263 blst_p2_uncompress,
2264 96,
2265 192,
2266 blst_p1_affine_in_g1,
2267 blst_p1_to_affine,
2268 blst_p1_from_affine,
2269 blst_p1_affine_serialize,
2270 blst_p1_affine_compress,
2271 blst_p1_deserialize,
2272 blst_p1_uncompress,
2273 48,
2274 96,
2275 blst_p2_add_or_double,
2276 blst_p2_add_or_double_affine,
2277 blst_p2_cneg,
2278 blst_p1_add_or_double,
2279 blst_p1_add_or_double_affine,
2280 blst_p2_affine_is_inf,
2281 blst_p1_affine_is_inf,
2282 blst_p1_in_g1,
2283 );
2284}
2285
2286pub trait MultiPoint {
2287 type Output;
2288
2289 fn mult(&self, scalars: &[u8], nbits: usize) -> Self::Output;
2290 fn add(&self) -> Self::Output;
2291 fn validate(&self) -> Result<(), BLST_ERROR> {
2292 Err(BLST_ERROR::BLST_POINT_NOT_IN_GROUP)
2293 }
2294}
2295
2296#[cfg(feature = "std")]
2297include!("pippenger.rs");
2298
2299#[cfg(not(feature = "std"))]
2300include!("pippenger-no_std.rs");
2301
2302#[cfg(test)]
2303mod fp12_test {
2304 use super::*;
2305 use rand::{RngCore, SeedableRng};
2306 use rand_chacha::ChaCha20Rng;
2307
2308 #[test]
2309 fn miller_loop_n() {
2310 const npoints: usize = 97;
2311 const nbits: usize = 64;
2312 const nbytes: usize = (nbits + 7) / 8;
2313
2314 let mut scalars = Box::new([0u8; nbytes * npoints]);
2315 ChaCha20Rng::from_entropy().fill_bytes(scalars.as_mut());
2316
2317 let mut p1s: Vec<blst_p1> = Vec::with_capacity(npoints);
2318 let mut p2s: Vec<blst_p2> = Vec::with_capacity(npoints);
2319
2320 unsafe {
2321 p1s.set_len(npoints);
2322 p2s.set_len(npoints);
2323
2324 for i in 0..npoints {
2325 blst_p1_mult(
2326 &mut p1s[i],
2327 blst_p1_generator(),
2328 &scalars[i * nbytes],
2329 32,
2330 );
2331 blst_p2_mult(
2332 &mut p2s[i],
2333 blst_p2_generator(),
2334 &scalars[i * nbytes + 4],
2335 32,
2336 );
2337 }
2338 }
2339
2340 let ps = p1_affines::from(&p1s);
2341 let qs = p2_affines::from(&p2s);
2342
2343 let mut naive = blst_fp12::default();
2344 for i in 0..npoints {
2345 naive *= blst_fp12::miller_loop(&qs[i], &ps[i]);
2346 }
2347
2348 assert_eq!(
2349 naive,
2350 blst_fp12::miller_loop_n(qs.as_slice(), ps.as_slice())
2351 );
2352 }
2353}
2354
2355#[cfg(test)]
2356mod sk_test {
2357 use super::*;
2358 use rand::{RngCore, SeedableRng};
2359 use rand_chacha::ChaCha20Rng;
2360
2361 #[test]
2362 fn inverse() {
2363 let mut bytes = [0u8; 64];
2364 ChaCha20Rng::from_entropy().fill_bytes(bytes.as_mut());
2365
2366 let mut sk = blst_scalar::default();
2367 let mut p1 = blst_p1::default();
2368 let mut p2 = blst_p2::default();
2369
2370 unsafe {
2371 blst_scalar_from_be_bytes(&mut sk, bytes.as_ptr(), bytes.len());
2372
2373 blst_p1_mult(&mut p1, blst_p1_generator(), sk.b.as_ptr(), 255);
2374 blst_sk_inverse(&mut sk, &sk);
2375 blst_p1_mult(&mut p1, &p1, sk.b.as_ptr(), 255);
2376
2377 blst_p2_mult(&mut p2, blst_p2_generator(), sk.b.as_ptr(), 255);
2378 blst_sk_inverse(&mut sk, &sk);
2379 blst_p2_mult(&mut p2, &p2, sk.b.as_ptr(), 255);
2380 }
2381
2382 assert_eq!(p1, unsafe { *blst_p1_generator() });
2383 assert_eq!(p2, unsafe { *blst_p2_generator() });
2384 }
2385}