Skip to main content

chia_bls/
signature.rs

1use crate::{Error, GTElement, PublicKey, Result, SecretKey};
2use blst::*;
3use chia_sha2::Sha256;
4use chia_traits::{Streamable, read_bytes};
5#[cfg(feature = "py-bindings")]
6use pyo3::exceptions::PyNotImplementedError;
7#[cfg(feature = "py-bindings")]
8use pyo3::prelude::*;
9#[cfg(feature = "py-bindings")]
10use pyo3::types::PyType;
11use std::borrow::Borrow;
12use std::fmt;
13use std::hash::{Hash, Hasher};
14use std::io::Cursor;
15use std::mem::MaybeUninit;
16use std::ops::{Add, AddAssign, Neg, SubAssign};
17
18// we use the augmented scheme
19pub(crate) const DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_";
20
21#[cfg_attr(
22    feature = "py-bindings",
23    pyo3::pyclass(name = "G2Element"),
24    derive(chia_py_streamable_macro::PyStreamable)
25)]
26#[derive(Clone, Default)]
27pub struct Signature(pub(crate) blst_p2);
28
29#[cfg(feature = "arbitrary")]
30impl<'a> arbitrary::Arbitrary<'a> for Signature {
31    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
32        use crate::SecretKey;
33        let sk = SecretKey::arbitrary(u)?;
34        Ok(sign(&sk, b"foobar"))
35    }
36}
37
38impl Signature {
39    pub fn from_bytes_unchecked(buf: &[u8; 96]) -> Result<Self> {
40        let p2 = unsafe {
41            let mut p2_affine = MaybeUninit::<blst_p2_affine>::uninit();
42            let ret = blst_p2_uncompress(p2_affine.as_mut_ptr(), buf.as_ptr());
43            if ret != BLST_ERROR::BLST_SUCCESS {
44                return Err(Error::InvalidSignature(ret));
45            }
46            let mut p2 = MaybeUninit::<blst_p2>::uninit();
47            blst_p2_from_affine(p2.as_mut_ptr(), &p2_affine.assume_init());
48            p2.assume_init()
49        };
50        Ok(Self(p2))
51    }
52
53    pub fn from_bytes(buf: &[u8; 96]) -> Result<Self> {
54        let ret = Self::from_bytes_unchecked(buf)?;
55        if ret.is_valid() {
56            Ok(ret)
57        } else {
58            Err(Error::InvalidSignature(BLST_ERROR::BLST_POINT_NOT_ON_CURVE))
59        }
60    }
61
62    pub fn from_uncompressed(buf: &[u8; 192]) -> Result<Self> {
63        let p2 = unsafe {
64            let mut p2_affine = MaybeUninit::<blst_p2_affine>::uninit();
65            let ret = blst_p2_deserialize(p2_affine.as_mut_ptr(), buf.as_ptr());
66            if ret != BLST_ERROR::BLST_SUCCESS {
67                return Err(Error::InvalidSignature(ret));
68            }
69            let mut p2 = MaybeUninit::<blst_p2>::uninit();
70            blst_p2_from_affine(p2.as_mut_ptr(), &p2_affine.assume_init());
71            p2.assume_init()
72        };
73        Ok(Self(p2))
74    }
75
76    pub fn to_bytes(&self) -> [u8; 96] {
77        unsafe {
78            let mut bytes = MaybeUninit::<[u8; 96]>::uninit();
79            blst_p2_compress(bytes.as_mut_ptr().cast::<u8>(), &raw const self.0);
80            bytes.assume_init()
81        }
82    }
83
84    pub fn generator() -> Self {
85        unsafe { Self(*blst_p2_generator()) }
86    }
87
88    pub fn aggregate(&mut self, sig: &Signature) {
89        unsafe {
90            blst_p2_add_or_double(&raw mut self.0, &raw const self.0, &raw const sig.0);
91        }
92    }
93
94    pub fn is_valid(&self) -> bool {
95        // Infinity was considered a valid G2Element in older Relic versions
96        // For historical compatibililty this behavior is maintained.
97        unsafe { blst_p2_is_inf(&raw const self.0) || blst_p2_in_g2(&raw const self.0) }
98    }
99
100    pub fn negate(&mut self) {
101        unsafe {
102            blst_p2_cneg(&raw mut self.0, true);
103        }
104    }
105
106    pub fn scalar_multiply(&mut self, int_bytes: &[u8]) {
107        unsafe {
108            let mut scalar = MaybeUninit::<blst_scalar>::uninit();
109            blst_scalar_from_be_bytes(scalar.as_mut_ptr(), int_bytes.as_ptr(), int_bytes.len());
110            blst_p2_mult(
111                &raw mut self.0,
112                &raw const self.0,
113                scalar.as_ptr().cast::<u8>(),
114                256,
115            );
116        }
117    }
118
119    pub fn pair(&self, other: &PublicKey) -> GTElement {
120        let ans = unsafe {
121            let mut ans = MaybeUninit::<blst_fp12>::uninit();
122            let mut aff1 = MaybeUninit::<blst_p1_affine>::uninit();
123            let mut aff2 = MaybeUninit::<blst_p2_affine>::uninit();
124
125            blst_p1_to_affine(aff1.as_mut_ptr(), &raw const other.0);
126            blst_p2_to_affine(aff2.as_mut_ptr(), &raw const self.0);
127
128            blst_miller_loop(ans.as_mut_ptr(), &aff2.assume_init(), &aff1.assume_init());
129            blst_final_exp(ans.as_mut_ptr(), ans.as_ptr());
130            ans.assume_init()
131        };
132        GTElement(ans)
133    }
134}
135
136impl Streamable for Signature {
137    fn update_digest(&self, digest: &mut Sha256) {
138        digest.update(self.to_bytes());
139    }
140
141    fn stream(&self, out: &mut Vec<u8>) -> chia_traits::chia_error::Result<()> {
142        out.extend_from_slice(&self.to_bytes());
143        Ok(())
144    }
145
146    fn parse<const TRUSTED: bool>(
147        input: &mut Cursor<&[u8]>,
148    ) -> chia_traits::chia_error::Result<Self> {
149        let input = read_bytes(input, 96)?.try_into().unwrap();
150        if TRUSTED {
151            Ok(Self::from_bytes_unchecked(input)?)
152        } else {
153            Ok(Self::from_bytes(input)?)
154        }
155    }
156}
157
158impl PartialEq for Signature {
159    fn eq(&self, other: &Self) -> bool {
160        unsafe { blst_p2_is_equal(&raw const self.0, &raw const other.0) }
161    }
162}
163impl Eq for Signature {}
164
165impl Hash for Signature {
166    fn hash<H: Hasher>(&self, state: &mut H) {
167        state.write(&self.to_bytes());
168    }
169}
170
171impl fmt::Debug for Signature {
172    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
173        formatter.write_fmt(format_args!(
174            "<G2Element {}>",
175            &hex::encode(self.to_bytes())
176        ))
177    }
178}
179
180impl AddAssign<&Signature> for Signature {
181    fn add_assign(&mut self, rhs: &Signature) {
182        unsafe {
183            blst_p2_add_or_double(&raw mut self.0, &raw const self.0, &raw const rhs.0);
184        }
185    }
186}
187
188impl Neg for Signature {
189    type Output = Signature;
190    fn neg(mut self) -> Self::Output {
191        self.negate();
192        self
193    }
194}
195
196impl Neg for &Signature {
197    type Output = Signature;
198    fn neg(self) -> Self::Output {
199        let mut ret = self.clone();
200        ret.negate();
201        ret
202    }
203}
204
205impl SubAssign<&Signature> for Signature {
206    fn sub_assign(&mut self, rhs: &Signature) {
207        unsafe {
208            let mut neg = rhs.clone();
209            blst_p2_cneg(&raw mut neg.0, true);
210            blst_p2_add_or_double(&raw mut self.0, &raw const self.0, &raw const neg.0);
211        }
212    }
213}
214
215impl Add<&Signature> for Signature {
216    type Output = Signature;
217    fn add(mut self, rhs: &Signature) -> Signature {
218        unsafe {
219            blst_p2_add_or_double(&raw mut self.0, &raw const self.0, &raw const rhs.0);
220            self
221        }
222    }
223}
224
225impl Add<&Signature> for &Signature {
226    type Output = Signature;
227    fn add(self, rhs: &Signature) -> Signature {
228        let p1 = unsafe {
229            let mut ret = MaybeUninit::<blst_p2>::uninit();
230            blst_p2_add_or_double(ret.as_mut_ptr(), &raw const self.0, &raw const rhs.0);
231            ret.assume_init()
232        };
233        Signature(p1)
234    }
235}
236
237#[cfg(feature = "serde")]
238impl serde::Serialize for Signature {
239    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
240    where
241        S: serde::Serializer,
242    {
243        chia_serde::ser_bytes(&self.to_bytes(), serializer, true)
244    }
245}
246
247#[cfg(feature = "serde")]
248impl<'de> serde::Deserialize<'de> for Signature {
249    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
250    where
251        D: serde::Deserializer<'de>,
252    {
253        Self::from_bytes(&chia_serde::de_bytes(deserializer)?).map_err(serde::de::Error::custom)
254    }
255}
256
257// validate a series of public keys (G1 points) and G2 points. These points are
258// paired and the resulting GT points are multiplied. If the resulting GT point
259// is the identity, the function returns true, otherwise false. To validate an
260// aggregate signature, include the G1 generator and the signature as one of the
261// pairs.
262pub fn aggregate_pairing<G1: Borrow<PublicKey>, G2: Borrow<Signature>, I>(data: I) -> bool
263where
264    I: IntoIterator<Item = (G1, G2)>,
265{
266    let mut data = data.into_iter().peekable();
267    if data.peek().is_none() {
268        return true;
269    }
270
271    let mut v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
272    let ctx = unsafe {
273        let ctx = v.as_mut_slice().as_mut_ptr().cast::<blst_pairing>();
274        blst_pairing_init(
275            ctx,
276            true, // hash
277            DST.as_ptr(),
278            DST.len(),
279        );
280        ctx
281    };
282
283    for (g1, g2) in data {
284        if !g1.borrow().is_valid() {
285            return false;
286        }
287        if !g2.borrow().is_valid() {
288            return false;
289        }
290
291        let g1_affine = unsafe {
292            let mut g1_affine = MaybeUninit::<blst_p1_affine>::uninit();
293            blst_p1_to_affine(g1_affine.as_mut_ptr(), &raw const g1.borrow().0);
294            g1_affine.assume_init()
295        };
296
297        let g2_affine = unsafe {
298            let mut g2_affine = MaybeUninit::<blst_p2_affine>::uninit();
299            blst_p2_to_affine(g2_affine.as_mut_ptr(), &raw const g2.borrow().0);
300            g2_affine.assume_init()
301        };
302
303        unsafe {
304            blst_pairing_raw_aggregate(ctx, &raw const g2_affine, &raw const g1_affine);
305        }
306    }
307
308    unsafe {
309        blst_pairing_commit(ctx);
310        blst_pairing_finalverify(ctx, std::ptr::null())
311    }
312}
313
314pub fn hash_to_g2(msg: &[u8]) -> Signature {
315    hash_to_g2_with_dst(msg, DST)
316}
317
318pub fn hash_to_g2_with_dst(msg: &[u8], dst: &[u8]) -> Signature {
319    let p2 = unsafe {
320        let mut p2 = MaybeUninit::<blst_p2>::uninit();
321        blst_hash_to_g2(
322            p2.as_mut_ptr(),
323            msg.as_ptr(),
324            msg.len(),
325            dst.as_ptr(),
326            dst.len(),
327            std::ptr::null(),
328            0,
329        );
330        p2.assume_init()
331    };
332    Signature(p2)
333}
334
335// aggregate the signatures into a single one. It can then be validated using
336// aggregate_verify()
337pub fn aggregate<Sig: Borrow<Signature>, I>(sigs: I) -> Signature
338where
339    I: IntoIterator<Item = Sig>,
340{
341    let mut ret = Signature::default();
342
343    for s in sigs {
344        ret.aggregate(s.borrow());
345    }
346    ret
347}
348
349// verify a signature given a single public key and message using the augmented
350// scheme, i.e. the public key is pre-pended to the message before hashed to G2.
351pub fn verify<Msg: AsRef<[u8]>>(sig: &Signature, key: &PublicKey, msg: Msg) -> bool {
352    unsafe {
353        let mut pubkey_affine = MaybeUninit::<blst_p1_affine>::uninit();
354        let mut sig_affine = MaybeUninit::<blst_p2_affine>::uninit();
355
356        blst_p1_to_affine(pubkey_affine.as_mut_ptr(), &raw const key.0);
357        blst_p2_to_affine(sig_affine.as_mut_ptr(), &raw const sig.0);
358
359        let mut augmented_msg = key.to_bytes().to_vec();
360        augmented_msg.extend_from_slice(msg.as_ref());
361
362        let err = blst_core_verify_pk_in_g1(
363            &pubkey_affine.assume_init(),
364            &sig_affine.assume_init(),
365            true, // hash
366            augmented_msg.as_ptr(),
367            augmented_msg.len(),
368            DST.as_ptr(),
369            DST.len(),
370            std::ptr::null(),
371            0,
372        );
373
374        err == BLST_ERROR::BLST_SUCCESS
375    }
376}
377
378// verify an aggregate signature given all public keys and messages.
379// Messages will been augmented with the public key.
380// returns true if the signature is valid.
381pub fn aggregate_verify<Pk: Borrow<PublicKey>, Msg: Borrow<[u8]>, I>(
382    sig: &Signature,
383    data: I,
384) -> bool
385where
386    I: IntoIterator<Item = (Pk, Msg)>,
387{
388    if !sig.is_valid() {
389        return false;
390    }
391
392    let mut data = data.into_iter().peekable();
393    if data.peek().is_none() {
394        return *sig == Signature::default();
395    }
396
397    let sig_gt = unsafe {
398        let mut sig_affine = MaybeUninit::<blst_p2_affine>::uninit();
399        let mut sig_gt = MaybeUninit::<blst_fp12>::uninit();
400        blst_p2_to_affine(sig_affine.as_mut_ptr(), &raw const sig.0);
401        blst_aggregated_in_g2(sig_gt.as_mut_ptr(), sig_affine.as_ptr());
402        sig_gt.assume_init()
403    };
404
405    let mut v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
406    let ctx = unsafe {
407        let ctx = v.as_mut_ptr().cast::<blst_pairing>();
408        blst_pairing_init(
409            ctx,
410            true, // hash
411            DST.as_ptr(),
412            DST.len(),
413        );
414        ctx
415    };
416
417    let mut aug_msg = Vec::<u8>::new();
418    for (pk, msg) in data {
419        if !pk.borrow().is_valid() {
420            return false;
421        }
422
423        let pk_affine = unsafe {
424            let mut pk_affine = MaybeUninit::<blst_p1_affine>::uninit();
425            blst_p1_to_affine(pk_affine.as_mut_ptr(), &raw const pk.borrow().0);
426            pk_affine.assume_init()
427        };
428
429        aug_msg.clear();
430        aug_msg.extend_from_slice(&pk.borrow().to_bytes());
431        aug_msg.extend_from_slice(msg.borrow());
432
433        let err = unsafe {
434            blst_pairing_aggregate_pk_in_g1(
435                ctx,
436                &raw const pk_affine,
437                std::ptr::null(),
438                aug_msg.as_ptr(),
439                aug_msg.len(),
440                std::ptr::null(),
441                0,
442            )
443        };
444
445        if err != BLST_ERROR::BLST_SUCCESS {
446            return false;
447        }
448    }
449
450    unsafe {
451        blst_pairing_commit(ctx);
452        blst_pairing_finalverify(ctx, &raw const sig_gt)
453    }
454}
455
456// verify an aggregate signature by pre-paired public keys and messages.
457// Messages having been augmented and hashed to G2 and then paired with the G1
458// public key.
459// returns true if the signature is valid.
460pub fn aggregate_verify_gt<Gt: Borrow<GTElement>, I>(sig: &Signature, data: I) -> bool
461where
462    I: IntoIterator<Item = Gt>,
463{
464    if !sig.is_valid() {
465        return false;
466    }
467
468    let mut data = data.into_iter();
469    let Some(agg) = data.next() else {
470        return *sig == Signature::default();
471    };
472
473    let mut agg = agg.borrow().clone();
474    for gt in data {
475        agg *= gt.borrow();
476    }
477
478    agg == sig.pair(&PublicKey::generator())
479}
480
481// Signs msg using sk without augmenting the message with the public key. This
482// function is used when the caller augments the message with some other public
483// key
484pub fn sign_raw<Msg: AsRef<[u8]>>(sk: &SecretKey, msg: Msg) -> Signature {
485    let p2 = unsafe {
486        let mut p2 = MaybeUninit::<blst_p2>::uninit();
487        blst_hash_to_g2(
488            p2.as_mut_ptr(),
489            msg.as_ref().as_ptr(),
490            msg.as_ref().len(),
491            DST.as_ptr(),
492            DST.len(),
493            std::ptr::null(),
494            0,
495        );
496        blst_sign_pk_in_g1(p2.as_mut_ptr(), p2.as_ptr(), &raw const sk.0);
497        p2.assume_init()
498    };
499    Signature(p2)
500}
501
502// Signs msg using sk using the augmented scheme, meaning the public key is
503// pre-pended to msg befire signing.
504pub fn sign<Msg: AsRef<[u8]>>(sk: &SecretKey, msg: Msg) -> Signature {
505    let mut aug_msg = sk.public_key().to_bytes().to_vec();
506    aug_msg.extend_from_slice(msg.as_ref());
507    sign_raw(sk, aug_msg)
508}
509
510#[cfg(feature = "py-bindings")]
511#[pyo3::pymethods]
512impl Signature {
513    #[classattr]
514    pub const SIZE: usize = 96;
515
516    #[new]
517    pub fn init() -> Self {
518        Self::default()
519    }
520
521    #[classmethod]
522    #[pyo3(name = "from_parent")]
523    pub fn from_parent(_cls: &Bound<'_, PyType>, _instance: &Self) -> PyResult<Py<PyAny>> {
524        Err(PyNotImplementedError::new_err(
525            "Signature does not support from_parent().",
526        ))
527    }
528
529    #[pyo3(name = "pair")]
530    pub fn py_pair(&self, other: &PublicKey) -> GTElement {
531        self.pair(other)
532    }
533
534    #[staticmethod]
535    #[pyo3(name = "generator")]
536    pub fn py_generator() -> Self {
537        Self::generator()
538    }
539
540    pub fn __str__(&self) -> String {
541        hex::encode(self.to_bytes())
542    }
543
544    #[must_use]
545    pub fn __add__(&self, rhs: &Self) -> Self {
546        self + rhs
547    }
548
549    pub fn __iadd__(&mut self, rhs: &Self) {
550        *self += rhs;
551    }
552}
553
554#[cfg(feature = "py-bindings")]
555mod pybindings {
556    use super::*;
557
558    use crate::parse_hex::parse_hex_string;
559
560    use chia_traits::{FromJsonDict, ToJsonDict};
561
562    impl ToJsonDict for Signature {
563        fn to_json_dict(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
564            let bytes = self.to_bytes();
565            Ok(("0x".to_string() + &hex::encode(bytes))
566                .into_pyobject(py)?
567                .into_any()
568                .unbind())
569        }
570    }
571
572    impl FromJsonDict for Signature {
573        fn from_json_dict(o: &Bound<'_, PyAny>) -> PyResult<Self> {
574            Ok(Self::from_bytes(
575                parse_hex_string(o, 96, "Signature")?
576                    .as_slice()
577                    .try_into()
578                    .unwrap(),
579            )?)
580        }
581    }
582}
583
584#[cfg(test)]
585mod tests {
586    use super::*;
587    use hex::FromHex;
588    use rand::rngs::StdRng;
589    use rand::{Rng, SeedableRng};
590    use rstest::rstest;
591
592    #[test]
593    fn test_from_bytes() {
594        let mut rng = StdRng::seed_from_u64(1337);
595        let mut data = [0u8; 96];
596        for _i in 0..50 {
597            rng.fill(data.as_mut_slice());
598            // just any random bytes are not a valid signature and should fail
599            match Signature::from_bytes(&data) {
600                Err(Error::InvalidSignature(err)) => {
601                    assert!(
602                        [
603                            BLST_ERROR::BLST_BAD_ENCODING,
604                            BLST_ERROR::BLST_POINT_NOT_ON_CURVE
605                        ]
606                        .contains(&err)
607                    );
608                }
609                Err(e) => {
610                    panic!("unexpected error from_bytes(): {e}");
611                }
612                Ok(v) => {
613                    panic!("unexpected value from_bytes(): {v:?}");
614                }
615            }
616        }
617    }
618
619    #[test]
620    fn test_default_is_valid() {
621        let sig = Signature::default();
622        assert!(sig.is_valid());
623    }
624
625    #[test]
626    fn test_infinity_is_valid() {
627        let mut data = [0u8; 96];
628        data[0] = 0xc0;
629        let sig = Signature::from_bytes(&data).unwrap();
630        assert!(sig.is_valid());
631    }
632
633    #[test]
634    fn test_is_valid() {
635        let mut rng = StdRng::seed_from_u64(1337);
636        let mut data = [0u8; 32];
637        let msg = [0u8; 32];
638        for _i in 0..50 {
639            rng.fill(data.as_mut_slice());
640            let sk = SecretKey::from_seed(&data);
641            let sig = sign(&sk, msg);
642            assert!(sig.is_valid());
643        }
644    }
645
646    #[test]
647    fn test_roundtrip() {
648        let mut rng = StdRng::seed_from_u64(1337);
649        let mut data = [0u8; 32];
650        let mut msg = [0u8; 32];
651        rng.fill(msg.as_mut_slice());
652        for _i in 0..50 {
653            rng.fill(data.as_mut_slice());
654            let sk = SecretKey::from_seed(&data);
655            let sig = sign(&sk, msg);
656            let bytes = sig.to_bytes();
657            let sig2 = Signature::from_bytes(&bytes).unwrap();
658            assert_eq!(sig, sig2);
659        }
660    }
661
662    #[test]
663    fn test_random_verify() {
664        let mut rng = StdRng::seed_from_u64(1337);
665        let mut data = [0u8; 32];
666        let mut msg = [0u8; 32];
667        rng.fill(msg.as_mut_slice());
668        for _i in 0..20 {
669            rng.fill(data.as_mut_slice());
670            let sk = SecretKey::from_seed(&data);
671            let pk = sk.public_key();
672            let sig = sign(&sk, msg);
673            assert!(verify(&sig, &pk, msg));
674
675            let bytes = sig.to_bytes();
676            let sig2 = Signature::from_bytes(&bytes).unwrap();
677            assert!(verify(&sig2, &pk, msg));
678        }
679    }
680
681    #[test]
682    fn test_verify() {
683        // test case from:
684        // from blspy import PrivateKey
685        // from blspy import AugSchemeMPL
686        // sk = PrivateKey.from_bytes(bytes.fromhex("52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb"))
687        // data = b"foobar"
688        // print(AugSchemeMPL.sign(sk, data))
689        let msg = b"foobar";
690        let sk = SecretKey::from_bytes(
691            &<[u8; 32]>::from_hex(
692                "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb",
693            )
694            .unwrap(),
695        )
696        .unwrap();
697
698        let sig = sign(&sk, msg);
699        assert!(verify(&sig, &sk.public_key(), msg));
700
701        assert_eq!(sig.to_bytes(), <[u8; 96]>::from_hex("b45825c0ee7759945c0189b4c38b7e54231ebadc83a851bec3bb7cf954a124ae0cc8e8e5146558332ea152f63bf8846e04826185ef60e817f271f8d500126561319203f9acb95809ed20c193757233454be1562a5870570941a84605bd2c9c9a").unwrap());
702    }
703
704    fn aug_msg_to_g2(pk: &PublicKey, msg: &[u8]) -> Signature {
705        let mut augmented = pk.to_bytes().to_vec();
706        augmented.extend_from_slice(msg);
707        hash_to_g2(augmented.as_slice())
708    }
709
710    #[test]
711    fn test_aggregate_signature() {
712        // from blspy import PrivateKey
713        // from blspy import AugSchemeMPL
714        // sk = PrivateKey.from_bytes(bytes.fromhex("52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb"))
715        // data = b"foobar"
716        // sk0 = AugSchemeMPL.derive_child_sk(sk, 0)
717        // sk1 = AugSchemeMPL.derive_child_sk(sk, 1)
718        // sk2 = AugSchemeMPL.derive_child_sk(sk, 2)
719        // sk3 = AugSchemeMPL.derive_child_sk(sk, 3)
720
721        // sig0 = AugSchemeMPL.sign(sk0, data)
722        // sig1 = AugSchemeMPL.sign(sk1, data)
723        // sig2 = AugSchemeMPL.sign(sk2, data)
724        // sig3 = AugSchemeMPL.sign(sk3, data)
725
726        // agg = AugSchemeMPL.aggregate([sig0, sig1, sig2, sig3])
727
728        // 87bce2c588f4257e2792d929834548c7d3af679272cb4f8e1d24cf4bf584dd287aa1d9f5e53a86f288190db45e1d100d0a5e936079a66a709b5f35394cf7d52f49dd963284cb5241055d54f8cf48f61bc1037d21cae6c025a7ea5e9f4d289a18
729
730        let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
731        let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
732        let msg = b"foobar";
733        let mut agg1 = Signature::default();
734        let mut agg2 = Signature::default();
735        let mut sigs = Vec::<Signature>::new();
736        let mut data = Vec::<(PublicKey, &[u8])>::new();
737        let mut pairs = Vec::<(PublicKey, Signature)>::new();
738        for idx in 0..4 {
739            let derived = sk.derive_hardened(idx as u32);
740            let pk = derived.public_key();
741            data.push((pk, msg));
742            let sig = sign(&derived, msg);
743            agg1.aggregate(&sig);
744            agg2 += &sig;
745            sigs.push(sig);
746            pairs.push((pk, aug_msg_to_g2(&pk, msg)));
747        }
748        let agg3 = aggregate(&sigs);
749        let agg4 = &sigs[0] + &sigs[1] + &sigs[2] + &sigs[3];
750
751        assert_eq!(agg1.to_bytes(), <[u8; 96]>::from_hex("87bce2c588f4257e2792d929834548c7d3af679272cb4f8e1d24cf4bf584dd287aa1d9f5e53a86f288190db45e1d100d0a5e936079a66a709b5f35394cf7d52f49dd963284cb5241055d54f8cf48f61bc1037d21cae6c025a7ea5e9f4d289a18").unwrap());
752        assert_eq!(agg1, agg2);
753        assert_eq!(agg1, agg3);
754        assert_eq!(agg1, agg4);
755
756        // ensure the aggregate signature verifies OK
757        assert!(aggregate_verify(&agg1, data.clone()));
758        assert!(aggregate_verify(&agg2, data.clone()));
759        assert!(aggregate_verify(&agg3, data.clone()));
760        assert!(aggregate_verify(&agg4, data.clone()));
761
762        pairs.push((-PublicKey::generator(), agg1));
763        assert!(aggregate_pairing(pairs.clone()));
764        // order does not matter
765        assert!(aggregate_pairing(pairs.into_iter().rev()));
766    }
767
768    #[rstest]
769    fn test_aggregate_gt_signature(#[values(0, 1, 2, 3, 4, 5, 100)] num_keys: usize) {
770        let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
771        let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
772        let msg = b"foobar";
773        let mut agg = Signature::default();
774        let mut gts = Vec::<GTElement>::new();
775        let mut pks = Vec::<PublicKey>::new();
776        for idx in 0..num_keys {
777            let derived = sk.derive_hardened(idx as u32);
778            let pk = derived.public_key();
779            let sig = sign(&derived, msg);
780            agg.aggregate(&sig);
781            gts.push(aug_msg_to_g2(&pk, msg).pair(&pk));
782            pks.push(pk);
783        }
784
785        assert!(aggregate_verify_gt(&agg, &gts));
786        assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
787
788        // the order of the GTElements does not matter
789        for _ in 0..num_keys {
790            gts.rotate_right(1);
791            pks.rotate_right(1);
792            assert!(aggregate_verify_gt(&agg, &gts));
793            assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
794        }
795        for _ in 0..num_keys {
796            gts.rotate_right(1);
797            pks.rotate_right(1);
798            assert!(!aggregate_verify_gt(&agg, &gts[1..]));
799            assert!(!aggregate_verify(
800                &agg,
801                pks[1..].iter().map(|pk| (pk, &msg[..]))
802            ));
803        }
804    }
805
806    #[test]
807    fn test_aggregate_duplicate_signature() {
808        let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
809        let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
810        let msg = b"foobar";
811        let mut agg = Signature::default();
812        let mut data = Vec::<(PublicKey, &[u8])>::new();
813        let mut pairs = Vec::<(PublicKey, Signature)>::new();
814        for _idx in 0..2 {
815            let pk = sk.public_key();
816            data.push((pk, msg));
817            agg.aggregate(&sign(&sk, *msg));
818
819            pairs.push((pk, aug_msg_to_g2(&pk, msg)));
820        }
821
822        assert_eq!(agg.to_bytes(), <[u8; 96]>::from_hex("a1cca6540a4a06d096cb5b5fc76af5fd099476e70b623b8c6e4cf02ffde94fc0f75f4e17c67a9e350940893306798a3519368b02dc3464b7270ea4ca233cfa85a38da9e25c9314e81270b54d1e773a2ec5c3e14c62dac7abdebe52f4688310d3").unwrap());
823
824        assert!(aggregate_verify(&agg, data));
825
826        pairs.push((-PublicKey::generator(), agg));
827        assert!(aggregate_pairing(pairs.clone()));
828        // order does not matter
829        assert!(aggregate_pairing(pairs.into_iter().rev()));
830    }
831
832    #[cfg(test)]
833    fn random_sk<R: Rng>(rng: &mut R) -> SecretKey {
834        let mut data = [0u8; 64];
835        rng.fill(data.as_mut_slice());
836        SecretKey::from_seed(&data)
837    }
838
839    #[test]
840    fn test_aggregate_signature_separate_msg() {
841        let mut rng = StdRng::seed_from_u64(1337);
842        let sk = [random_sk(&mut rng), random_sk(&mut rng)];
843        let pk = [sk[0].public_key(), sk[1].public_key()];
844        let msg: [&'static [u8]; 2] = [b"foo", b"foobar"];
845        let sig = [sign(&sk[0], msg[0]), sign(&sk[1], msg[1])];
846        let mut agg = Signature::default();
847        agg.aggregate(&sig[0]);
848        agg.aggregate(&sig[1]);
849
850        assert!(aggregate_verify(&agg, pk.iter().zip(msg)));
851        // order does not matter
852        assert!(aggregate_verify(&agg, pk.iter().zip(msg).rev()));
853    }
854
855    #[test]
856    fn test_aggregate_signature_identity() {
857        // when verifying 0 messages, an identity signature is considered valid
858        let empty = Vec::<(PublicKey, &[u8])>::new();
859        assert!(aggregate_verify(&Signature::default(), empty));
860
861        let pairs = vec![(-PublicKey::generator(), Signature::default())];
862        assert!(aggregate_pairing(pairs));
863    }
864
865    #[test]
866    fn test_invalid_aggregate_signature() {
867        let mut rng = StdRng::seed_from_u64(1337);
868        let sk = [random_sk(&mut rng), random_sk(&mut rng)];
869        let pk = [sk[0].public_key(), sk[1].public_key()];
870        let msg: [&'static [u8]; 2] = [b"foo", b"foobar"];
871        let sig = [sign(&sk[0], msg[0]), sign(&sk[1], msg[1])];
872        let g2s = [aug_msg_to_g2(&pk[0], msg[0]), aug_msg_to_g2(&pk[1], msg[1])];
873        let mut agg = Signature::default();
874        agg.aggregate(&sig[0]);
875        agg.aggregate(&sig[1]);
876
877        assert!(!aggregate_verify(&agg, [(&pk[0], msg[0])]));
878        assert!(!aggregate_verify(&agg, [(&pk[1], msg[1])]));
879        // public keys mixed with the wrong message
880        assert!(!aggregate_verify(
881            &agg,
882            [(&pk[0], msg[1]), (&pk[1], msg[0])]
883        ));
884        assert!(!aggregate_verify(
885            &agg,
886            [(&pk[1], msg[0]), (&pk[0], msg[1])]
887        ));
888
889        let gen_sig = (&-PublicKey::generator(), agg);
890        assert!(!aggregate_pairing([
891            (&pk[0], g2s[0].clone()),
892            gen_sig.clone()
893        ]));
894        assert!(!aggregate_pairing([
895            (&pk[1], g2s[1].clone()),
896            gen_sig.clone()
897        ]));
898        // public keys mixed with the wrong message
899        assert!(!aggregate_pairing([
900            (&pk[0], g2s[1].clone()),
901            (&pk[1], g2s[0].clone()),
902            gen_sig.clone()
903        ]));
904        assert!(!aggregate_pairing([
905            (&pk[1], g2s[0].clone()),
906            (&pk[0], g2s[1].clone()),
907            gen_sig.clone()
908        ]));
909    }
910
911    #[test]
912    fn test_vector_2_aggregate_of_aggregates() {
913        // test case from: bls-signatures/src/test.cpp
914        // "Chia test vector 2 (Augmented, aggregate of aggregates)"
915        let message1 = [1_u8, 2, 3, 40];
916        let message2 = [5_u8, 6, 70, 201];
917        let message3 = [9_u8, 10, 11, 12, 13];
918        let message4 = [15_u8, 63, 244, 92, 0, 1];
919
920        let sk1 = SecretKey::from_seed(&[2_u8; 32]);
921        let sk2 = SecretKey::from_seed(&[3_u8; 32]);
922
923        let pk1 = sk1.public_key();
924        let pk2 = sk2.public_key();
925
926        let sig1 = sign(&sk1, message1);
927        let sig2 = sign(&sk2, message2);
928        let sig3 = sign(&sk2, message1);
929        let sig4 = sign(&sk1, message3);
930        let sig5 = sign(&sk1, message1);
931        let sig6 = sign(&sk1, message4);
932
933        let agg_sig_l = aggregate([sig1, sig2]);
934        let agg_sig_r = aggregate([sig3, sig4, sig5]);
935        let aggsig = aggregate([agg_sig_l, agg_sig_r, sig6]);
936
937        assert!(aggregate_verify(
938            &aggsig,
939            [
940                (&pk1, message1.as_ref()),
941                (&pk2, message2.as_ref()),
942                (&pk2, message1.as_ref()),
943                (&pk1, message3.as_ref()),
944                (&pk1, message1.as_ref()),
945                (&pk1, message4.as_ref())
946            ]
947        ));
948
949        assert_eq!(
950            aggsig.to_bytes(),
951            <[u8; 96]>::from_hex(
952                "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b6c4e9acd4\
953            6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc25ca964871\
954            997b9bceeab37a4c2565876da19382ea32a962200"
955            )
956            .unwrap()
957        );
958    }
959
960    #[test]
961    fn test_signature_zero_key() {
962        // test case from: bls-signatures/src/test.cpp
963        // "Should sign with the zero key"
964        let sk = SecretKey::from_bytes(&[0; 32]).unwrap();
965        assert_eq!(sign(&sk, [1_u8, 2, 3]), Signature::default());
966    }
967
968    #[test]
969    fn test_aggregate_many_g2_elements_diff_message() {
970        // test case from: bls-signatures/src/test.cpp
971        // "Should Aug aggregate many G2Elements, diff message"
972
973        let mut rng = StdRng::seed_from_u64(1337);
974
975        let mut pairs = Vec::<(PublicKey, Vec<u8>)>::new();
976        let mut sigs = Vec::<Signature>::new();
977
978        for i in 0..80 {
979            let message = vec![0_u8, 100, 2, 45, 64, 12, 12, 63, i];
980            let sk = random_sk(&mut rng);
981            let sig = sign(&sk, &message);
982            pairs.push((sk.public_key(), message));
983            sigs.push(sig);
984        }
985
986        let aggsig = aggregate(sigs);
987
988        assert!(aggregate_verify(&aggsig, pairs));
989    }
990
991    #[test]
992    fn test_aggregate_identity() {
993        // test case from: bls-signatures/src/test.cpp
994        // "Aggregate Verification of zero items with infinity should pass"
995        let sig = Signature::default();
996        let aggsig = aggregate([&sig]);
997        assert_eq!(aggsig, sig);
998        assert_eq!(aggsig, Signature::default());
999
1000        let pairs: [(&PublicKey, &[u8]); 0] = [];
1001        assert!(aggregate_verify(&aggsig, pairs));
1002    }
1003
1004    #[test]
1005    fn test_aggregate_multiple_levels_degenerate() {
1006        // test case from: bls-signatures/src/test.cpp
1007        // "Should aggregate with multiple levels, degenerate"
1008
1009        let mut rng = StdRng::seed_from_u64(1337);
1010
1011        let message1 = [100_u8, 2, 254, 88, 90, 45, 23];
1012        let sk1 = random_sk(&mut rng);
1013        let pk1 = sk1.public_key();
1014        let mut agg_sig = sign(&sk1, message1);
1015        let mut pairs: Vec<(PublicKey, &[u8])> = vec![(pk1, &message1)];
1016
1017        for _i in 0..10 {
1018            let sk = random_sk(&mut rng);
1019            let pk = sk.public_key();
1020            pairs.push((pk, &message1));
1021            let sig = sign(&sk, message1);
1022            agg_sig.aggregate(&sig);
1023        }
1024        assert!(aggregate_verify(&agg_sig, pairs));
1025    }
1026
1027    #[test]
1028    fn test_aggregate_multiple_levels_different_messages() {
1029        // test case from: bls-signatures/src/test.cpp
1030        // "Should aggregate with multiple levels, different messages"
1031
1032        let mut rng = StdRng::seed_from_u64(1337);
1033
1034        let message1 = [100_u8, 2, 254, 88, 90, 45, 23];
1035        let message2 = [192_u8, 29, 2, 0, 0, 45, 23];
1036        let message3 = [52_u8, 29, 2, 0, 0, 45, 102];
1037        let message4 = [99_u8, 29, 2, 0, 0, 45, 222];
1038
1039        let sk1 = random_sk(&mut rng);
1040        let sk2 = random_sk(&mut rng);
1041
1042        let pk1 = sk1.public_key();
1043        let pk2 = sk2.public_key();
1044
1045        let sig1 = sign(&sk1, message1);
1046        let sig2 = sign(&sk2, message2);
1047        let sig3 = sign(&sk2, message3);
1048        let sig4 = sign(&sk1, message4);
1049
1050        let agg_sig_l = aggregate([sig1, sig2]);
1051        let agg_sig_r = aggregate([sig3, sig4]);
1052        let agg_sig = aggregate([agg_sig_l, agg_sig_r]);
1053
1054        let all_pairs: [(&PublicKey, &[u8]); 4] = [
1055            (&pk1, &message1),
1056            (&pk2, &message2),
1057            (&pk2, &message3),
1058            (&pk1, &message4),
1059        ];
1060        assert!(aggregate_verify(&agg_sig, all_pairs));
1061    }
1062
1063    #[test]
1064    fn test_aug_scheme() {
1065        // test case from: bls-signatures/src/test.cpp
1066        // "Aug Scheme"
1067
1068        let msg1 = [7_u8, 8, 9];
1069        let msg2 = [10_u8, 11, 12];
1070
1071        let sk1 = SecretKey::from_seed(&[4_u8; 32]);
1072        let pk1 = sk1.public_key();
1073        let pk1v = pk1.to_bytes();
1074        let sig1 = sign(&sk1, msg1);
1075        let sig1v = sig1.to_bytes();
1076
1077        assert!(verify(&sig1, &pk1, msg1));
1078        assert!(verify(
1079            &Signature::from_bytes(&sig1v).unwrap(),
1080            &PublicKey::from_bytes(&pk1v).unwrap(),
1081            msg1
1082        ));
1083
1084        let sk2 = SecretKey::from_seed(&[5_u8; 32]);
1085        let pk2 = sk2.public_key();
1086        let pk2v = pk2.to_bytes();
1087        let sig2 = sign(&sk2, msg2);
1088        let sig2v = sig2.to_bytes();
1089
1090        assert!(verify(&sig2, &pk2, msg2));
1091        assert!(verify(
1092            &Signature::from_bytes(&sig2v).unwrap(),
1093            &PublicKey::from_bytes(&pk2v).unwrap(),
1094            msg2
1095        ));
1096
1097        // Wrong G2Element
1098        assert!(!verify(&sig2, &pk1, msg1));
1099        assert!(!verify(
1100            &Signature::from_bytes(&sig2v).unwrap(),
1101            &PublicKey::from_bytes(&pk1v).unwrap(),
1102            msg1
1103        ));
1104        // Wrong msg
1105        assert!(!verify(&sig1, &pk1, msg2));
1106        assert!(!verify(
1107            &Signature::from_bytes(&sig1v).unwrap(),
1108            &PublicKey::from_bytes(&pk1v).unwrap(),
1109            msg2
1110        ));
1111        // Wrong pk
1112        assert!(!verify(&sig1, &pk2, msg1));
1113        assert!(!verify(
1114            &Signature::from_bytes(&sig1v).unwrap(),
1115            &PublicKey::from_bytes(&pk2v).unwrap(),
1116            msg1
1117        ));
1118
1119        let aggsig = aggregate([sig1, sig2]);
1120        let aggsigv = aggsig.to_bytes();
1121        let pairs: [(&PublicKey, &[u8]); 2] = [(&pk1, &msg1), (&pk2, &msg2)];
1122        assert!(aggregate_verify(&aggsig, pairs));
1123        assert!(aggregate_verify(
1124            &Signature::from_bytes(&aggsigv).unwrap(),
1125            pairs
1126        ));
1127    }
1128
1129    #[test]
1130    fn test_hash() {
1131        fn hash<T: Hash>(v: T) -> u64 {
1132            use std::collections::hash_map::DefaultHasher;
1133            let mut h = DefaultHasher::new();
1134            v.hash(&mut h);
1135            h.finish()
1136        }
1137
1138        let mut rng = StdRng::seed_from_u64(1337);
1139        let mut data = [0u8; 32];
1140        rng.fill(data.as_mut_slice());
1141        let sk = SecretKey::from_seed(&data);
1142        let sig1 = sign(&sk, [0, 1, 2]);
1143        let sig2 = sign(&sk, [0, 1, 2, 3]);
1144
1145        assert!(hash(sig1) != hash(sig2));
1146        assert_eq!(hash(sign(&sk, [0, 1, 2])), hash(sign(&sk, [0, 1, 2])));
1147    }
1148
1149    #[test]
1150    fn test_debug() {
1151        let mut data = [0u8; 96];
1152        data[0] = 0xc0;
1153        let sig = Signature::from_bytes(&data).unwrap();
1154        assert_eq!(
1155            format!("{sig:?}"),
1156            format!("<G2Element {}>", hex::encode(data))
1157        );
1158    }
1159
1160    #[test]
1161    fn test_generator() {
1162        assert_eq!(
1163            hex::encode(Signature::generator().to_bytes()),
1164            "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"
1165        );
1166    }
1167
1168    // test cases from zksnark test in chia_rs
1169    #[rstest]
1170    #[case(
1171        "0a7ecb9c6d6f0af8d922c9b348d686f7f827c5f5d7a53036e5dd6c4cfe088806375d730251df57c03b0eaa41ca2a9cc51817cfd6118c065e9b337e42a6b66621e2ffa79f576ae57dcb4916459b0131d42383b790a4f60c5aeb339b61a78d85a808b73e0701084dc16b5d7aa8c2f5385f83a217bc29934d0d02c51365410232e3c0288438e3110aa6e8cdef7bd32c46d60d0104952aaa0f0545cbe1548b70eed8b543ce19ede34cc51a387d092221417db0253f4651666b17303e225eac706107",
1172        "8a7ecb9c6d6f0af8d922c9b348d686f7f827c5f5d7a53036e5dd6c4cfe088806375d730251df57c03b0eaa41ca2a9cc51817cfd6118c065e9b337e42a6b66621e2ffa79f576ae57dcb4916459b0131d42383b790a4f60c5aeb339b61a78d85a8"
1173    )]
1174    #[case(
1175        "13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
1176        "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"
1177    )]
1178    #[case(
1179        "140acf170629d78244fb753f05fb79578add9217add53996d5de7c3005880c0dea903f851d6be749ebfb81c9721871370ef60428444d76f4ff81515628a4eb63e72c3cd7651a23c4eca109d1d88fec5a53626b36c76407926f308366b5ded1b219a481d87c6f87a4021fa8aa32851874f01b3eb011f6ed69c7884717fb0f5239bdc7310c2bc287659cd4a93976deaac20f4a21f0b004c767be4a21f36861616a5399b3e27431dc8133f325603230eaf1debdce8077105ab46baafa4836842305",
1180        "b40acf170629d78244fb753f05fb79578add9217add53996d5de7c3005880c0dea903f851d6be749ebfb81c9721871370ef60428444d76f4ff81515628a4eb63e72c3cd7651a23c4eca109d1d88fec5a53626b36c76407926f308366b5ded1b2"
1181    )]
1182    fn test_from_uncompressed(#[case] input: &str, #[case] expect: &str) {
1183        let input = hex::decode(input).unwrap();
1184        let g2 = Signature::from_uncompressed(input.as_slice().try_into().unwrap()).unwrap();
1185        let compressed = g2.to_bytes();
1186        assert_eq!(hex::encode(compressed), expect);
1187    }
1188
1189    #[test]
1190    fn test_negate_roundtrip() {
1191        let mut rng = StdRng::seed_from_u64(1337);
1192        let mut data = [0u8; 32];
1193        let mut msg = [0u8; 32];
1194        rng.fill(msg.as_mut_slice());
1195        for _i in 0..50 {
1196            rng.fill(data.as_mut_slice());
1197            let sk = SecretKey::from_seed(&data);
1198            let g2 = sign(&sk, msg);
1199
1200            let mut g2_neg = g2.clone();
1201            g2_neg.negate();
1202            assert!(g2_neg != g2);
1203
1204            g2_neg.negate();
1205            assert!(g2_neg == g2);
1206        }
1207    }
1208
1209    #[test]
1210    fn test_negate_infinity() {
1211        let g2 = Signature::default();
1212        let mut g2_neg = g2.clone();
1213        // negate on infinity is a no-op
1214        g2_neg.negate();
1215        assert!(g2_neg == g2);
1216    }
1217
1218    #[test]
1219    fn test_negate() {
1220        let mut rng = StdRng::seed_from_u64(1337);
1221        let mut data = [0u8; 32];
1222        let mut msg = [0u8; 32];
1223        rng.fill(msg.as_mut_slice());
1224        for _i in 0..50 {
1225            rng.fill(data.as_mut_slice());
1226            let sk = SecretKey::from_seed(&data);
1227            let g2 = sign(&sk, msg);
1228            let mut g2_neg = g2.clone();
1229            g2_neg.negate();
1230
1231            let mut g2_double = g2.clone();
1232            // adding the negative undoes adding the positive
1233            g2_double += &g2;
1234            assert!(g2_double != g2);
1235            g2_double += &g2_neg;
1236            assert!(g2_double == g2);
1237        }
1238    }
1239
1240    #[test]
1241    fn test_scalar_multiply() {
1242        let mut rng = StdRng::seed_from_u64(1337);
1243        let mut data = [0u8; 32];
1244        let mut msg = [0u8; 32];
1245        rng.fill(msg.as_mut_slice());
1246        for _i in 0..50 {
1247            rng.fill(data.as_mut_slice());
1248            let sk = SecretKey::from_seed(&data);
1249            let mut g2 = sign(&sk, msg);
1250            let mut g2_double = g2.clone();
1251            g2_double += &g2;
1252            assert!(g2_double != g2);
1253            // scalar multiply by 2 is the same as adding oneself
1254            g2.scalar_multiply(&[2]);
1255            assert!(g2_double == g2);
1256        }
1257    }
1258
1259    #[test]
1260    fn test_hash_to_g2_different_dst() {
1261        const DEFAULT_DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_";
1262        const CUSTOM_DST: &[u8] = b"foobar";
1263
1264        let mut rng = StdRng::seed_from_u64(1337);
1265        let mut msg = [0u8; 32];
1266        for _i in 0..50 {
1267            rng.fill(&mut msg);
1268            let default_hash = hash_to_g2(&msg);
1269            assert_eq!(default_hash, hash_to_g2_with_dst(&msg, DEFAULT_DST));
1270            assert!(default_hash != hash_to_g2_with_dst(&msg, CUSTOM_DST));
1271        }
1272    }
1273
1274    // test cases from clvm_rs
1275    #[rstest]
1276    #[case(
1277        "abcdef0123456789",
1278        "92596412844e12c4733b5a6bfc5727cde4c20b345665d2de99de163266f3ba6a944c6c0fdd9d9fe57b9a4acb769bf3780456f8aab4cd41a70836dba57a5278a85fbd18eb96a2b56cfbda853186c9d190c43e63bc3e6a181aed692e97bbdb1944"
1279    )]
1280    fn test_hash_to_g2(#[case] input: &str, #[case] expect: &str) {
1281        let g2 = hash_to_g2(input.as_bytes());
1282        assert_eq!(hex::encode(g2.to_bytes()), expect);
1283    }
1284
1285    // test cases from clvm_rs
1286    #[rstest]
1287    #[case(
1288        "abcdef0123456789",
1289        "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_",
1290        "8ee1ff66094b8975401c86ad424076d97fed9c2025db5f9dfde6ed455c7bff34b55e96379c1f9ee3c173633587f425e50aed3e807c6c7cd7bed35d40542eee99891955b2ea5321ebde37172e2c01155138494c2d725b03c02765828679bf011e"
1291    )]
1292    #[case(
1293        "abcdef0123456789",
1294        "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_",
1295        "92596412844e12c4733b5a6bfc5727cde4c20b345665d2de99de163266f3ba6a944c6c0fdd9d9fe57b9a4acb769bf3780456f8aab4cd41a70836dba57a5278a85fbd18eb96a2b56cfbda853186c9d190c43e63bc3e6a181aed692e97bbdb1944"
1296    )]
1297    fn test_hash_to_g2_with_dst(#[case] input: &str, #[case] dst: &str, #[case] expect: &str) {
1298        let g2 = hash_to_g2_with_dst(input.as_bytes(), dst.as_bytes());
1299        assert_eq!(hex::encode(g2.to_bytes()), expect);
1300    }
1301}
1302
1303#[cfg(test)]
1304#[cfg(feature = "py-bindings")]
1305mod pytests {
1306    use super::*;
1307
1308    use pyo3::Python;
1309    use rand::rngs::StdRng;
1310    use rand::{Rng, SeedableRng};
1311    use rstest::rstest;
1312
1313    #[test]
1314    fn test_json_dict_roundtrip() {
1315        Python::initialize();
1316        let mut rng = StdRng::seed_from_u64(1337);
1317        let mut data = [0u8; 32];
1318        let mut msg = [0u8; 10];
1319        for _i in 0..50 {
1320            rng.fill(data.as_mut_slice());
1321            rng.fill(msg.as_mut_slice());
1322            let sk = SecretKey::from_seed(&data);
1323            let sig = sign(&sk, msg);
1324            Python::attach(|py| {
1325                let string = sig.to_json_dict(py).expect("to_json_dict");
1326                let py_class = py.get_type::<Signature>();
1327                let sig2 = Signature::from_json_dict(&py_class, py, string.bind(py))
1328                    .unwrap()
1329                    .extract(py)
1330                    .unwrap();
1331                assert_eq!(sig, sig2);
1332            });
1333        }
1334    }
1335
1336    #[rstest]
1337    #[case(
1338        "0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e",
1339        "Signature, invalid length 95 expected 96"
1340    )]
1341    #[case(
1342        "0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00",
1343        "Signature, invalid length 97 expected 96"
1344    )]
1345    #[case(
1346        "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e",
1347        "Signature, invalid length 95 expected 96"
1348    )]
1349    #[case(
1350        "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00",
1351        "Signature, invalid length 97 expected 96"
1352    )]
1353    #[case(
1354        "00r102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f",
1355        "invalid hex"
1356    )]
1357    fn test_json_dict(#[case] input: &str, #[case] msg: &str) {
1358        Python::initialize();
1359        Python::attach(|py| {
1360            let py_class = py.get_type::<Signature>();
1361            let err = Signature::from_json_dict(
1362                &py_class,
1363                py,
1364                &input.to_string().into_pyobject(py).unwrap().into_any(),
1365            )
1366            .unwrap_err();
1367            assert_eq!(err.value(py).to_string(), msg.to_string());
1368        });
1369    }
1370}