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
18pub(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 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
257pub 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, 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
335pub 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
349pub 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, 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
378pub 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, 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
456pub 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
481pub 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
502pub 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 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 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 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 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 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, >s));
786 assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
787
788 for _ in 0..num_keys {
790 gts.rotate_right(1);
791 pks.rotate_right(1);
792 assert!(aggregate_verify_gt(&agg, >s));
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, >s[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 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 assert!(aggregate_verify(&agg, pk.iter().zip(msg).rev()));
853 }
854
855 #[test]
856 fn test_aggregate_signature_identity() {
857 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 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 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 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 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 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 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 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 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 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 assert!(!verify(&sig2, &pk1, msg1));
1099 assert!(!verify(
1100 &Signature::from_bytes(&sig2v).unwrap(),
1101 &PublicKey::from_bytes(&pk1v).unwrap(),
1102 msg1
1103 ));
1104 assert!(!verify(&sig1, &pk1, msg2));
1106 assert!(!verify(
1107 &Signature::from_bytes(&sig1v).unwrap(),
1108 &PublicKey::from_bytes(&pk1v).unwrap(),
1109 msg2
1110 ));
1111 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 #[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 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 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 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 #[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 #[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}