Skip to main content

blst/
lib.rs

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