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