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::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            // Bypass 'lifetime limitations by brute force. It works,
59            // because we explicitly join the threads...
60            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        /// Secret Key
550        #[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            /// Deterministically generate a secret key from key material
559            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            // sk_to_pk
675            pub fn sk_to_pk(&self) -> PublicKey {
676                // TODO - would the user like the serialized/compressed pk as well?
677                let mut pk_aff = PublicKey::default();
678                //let mut pk_ser = [0u8; $pk_ser_size];
679
680                unsafe {
681                    $sk_to_pk(
682                        //pk_ser.as_mut_ptr(),
683                        ptr::null_mut(),
684                        &mut pk_aff.point,
685                        &self.value,
686                    );
687                }
688                pk_aff
689            }
690
691            // Sign
692            pub fn sign(
693                &self,
694                msg: &[u8],
695                dst: &[u8],
696                aug: &[u8],
697            ) -> Signature {
698                // TODO - would the user like the serialized/compressed sig as well?
699                let mut q = <$sig>::default();
700                let mut sig_aff = <$sig_aff>::default();
701                //let mut sig_ser = [0u8; $sig_ser_size];
702                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            // TODO - formally speaking application is entitled to have
718            // ultimate control over secret key storage, which means that
719            // corresponding serialization/deserialization subroutines
720            // should accept reference to where to store the result, as
721            // opposite to returning one.
722
723            // serialize
724            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            // deserialize
733            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        // From<by-value> traits are not provided to discourage duplication
780        // of the secret key material.
781        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            // Core operations
810
811            // key_validate
812            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            // Serdes
839
840            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        // Trait for equality comparisons which are equivalence relations.
894        //
895        // This means, that in addition to a == b and a != b being strict
896        // inverses, the equality must be reflexive, symmetric and transitive.
897        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            // Aggregate
969            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                // TODO - threading
1015                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            // sig_infcheck, check for infinity, is a way to avoid going
1096            // into resource-consuming verification. Passing 'false' is
1097            // always cryptographically safe, but application might want
1098            // to guard against obviously bogus individual[!] signatures.
1099            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                // TODO - check msg uniqueness?
1208
1209                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(&gtsig))
1266                {
1267                    BLST_ERROR::BLST_SUCCESS
1268                } else {
1269                    BLST_ERROR::BLST_VERIFY_FAIL
1270                }
1271            }
1272
1273            // pks are assumed to be verified for proof of possession,
1274            // which implies that they are already group-checked
1275            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            // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
1307            #[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                // TODO - check msg uniqueness?
1329
1330                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                        // TODO - engage multi-point mul-n-add for larger
1344                        // amount of inputs...
1345                        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                // TODO - check msg uniqueness?
1407
1408                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        // Trait for equality comparisons which are equivalence relations.
1504        //
1505        // This means, that in addition to a == b and a != b being strict
1506        // inverses, the equality must be reflexive, symmetric and transitive.
1507        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            // Aggregate
1588            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                    // We can't actually judge if input is individual or
1597                    // aggregated signature, so we can't enforce infinity
1598                    // check.
1599                    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                // TODO - threading
1637                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            // Testing only - do not use for production
1765            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                // Swap message/public key pairs to create bad signature
1844                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                // Swap message/public key pairs to create bad signature
1865                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                    // Create public keys
1885                    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                    // Create random message for pks to all sign
1897                    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                    // Generate signature for each key pair
1902                    let sigs_i = sks_i
1903                        .iter()
1904                        .map(|sk| sk.sign(&msgs[i], dst, &[]))
1905                        .collect::<Vec<Signature>>();
1906
1907                    // Test each current single signature
1908                    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                    // Test current aggregate signature
1930                    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                    // negative test
1940                    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                    // aggregate public keys and push into vec
1951                    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                    // Test current aggregate signature with aggregated pks
1960                    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                    // negative test
1966                    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                    // create random values
1975                    let mut vals = [0u64; 4];
1976                    vals[0] = rng.next_u64();
1977                    while vals[0] == 0 {
1978                        // Reject zero as it is used for multiplication.
1979                        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                // negative tests (use reverse msgs, pks, and sigs)
2013                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                // generate a sk, pk, and sig, and make sure it signs
2078                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                // roundtrip through serde
2087                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                // check that we got back the right things
2097                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                    // BLS signatures are deterministic, so this establishes
2116                    // that sk == sk_des
2117                    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                // Create public keys
2130                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                // Create random message for pks to all sign
2139                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                // Generate signature for each key pair
2144                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                // create random values
2152                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                        // Reject zero as it is used for multiplication.
2157                        r = rng.next_u64();
2158                    }
2159                    rands.extend_from_slice(&r.to_le_bytes());
2160                }
2161
2162                // Sanity test each current single signature
2163                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                // sanity test aggregated signature
2171                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                // test multi-point aggregation using add
2181                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                // test multi-point aggregation using mult
2187                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}