1use crate::crypto::ed25519::{
7 ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH, Ed25519PublicKey, Ed25519Signature,
8};
9use crate::crypto::traits::{PublicKey, Verifier};
10use crate::error::{AptosError, AptosResult};
11use serde::{Deserialize, Serialize};
12use std::fmt;
13
14pub const MAX_NUM_OF_KEYS: usize = 32;
16
17const _: () = assert!(MAX_NUM_OF_KEYS <= u8::MAX as usize);
19
20pub const MIN_THRESHOLD: u8 = 1;
22
23#[derive(Clone, PartialEq, Eq)]
37pub struct MultiEd25519PublicKey {
38 public_keys: Vec<Ed25519PublicKey>,
40 threshold: u8,
42}
43
44impl MultiEd25519PublicKey {
45 pub fn new(public_keys: Vec<Ed25519PublicKey>, threshold: u8) -> AptosResult<Self> {
60 if public_keys.is_empty() {
61 return Err(AptosError::InvalidPublicKey(
62 "multi-Ed25519 requires at least one public key".into(),
63 ));
64 }
65 if public_keys.len() > MAX_NUM_OF_KEYS {
66 return Err(AptosError::InvalidPublicKey(format!(
67 "multi-Ed25519 supports at most {} keys, got {}",
68 MAX_NUM_OF_KEYS,
69 public_keys.len()
70 )));
71 }
72 if threshold < MIN_THRESHOLD {
73 return Err(AptosError::InvalidPublicKey(
74 "threshold must be at least 1".into(),
75 ));
76 }
77 if threshold as usize > public_keys.len() {
78 return Err(AptosError::InvalidPublicKey(format!(
79 "threshold {} exceeds number of keys {}",
80 threshold,
81 public_keys.len()
82 )));
83 }
84 Ok(Self {
85 public_keys,
86 threshold,
87 })
88 }
89
90 pub fn num_keys(&self) -> usize {
92 self.public_keys.len()
93 }
94
95 pub fn threshold(&self) -> u8 {
97 self.threshold
98 }
99
100 pub fn public_keys(&self) -> &[Ed25519PublicKey] {
102 &self.public_keys
103 }
104
105 pub fn to_bytes(&self) -> Vec<u8> {
109 let mut bytes = Vec::with_capacity(self.public_keys.len() * ED25519_PUBLIC_KEY_LENGTH + 1);
110 for pk in &self.public_keys {
111 bytes.extend_from_slice(&pk.to_bytes());
112 }
113 bytes.push(self.threshold);
114 bytes
115 }
116
117 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
128 if bytes.is_empty() {
129 return Err(AptosError::InvalidPublicKey("empty bytes".into()));
130 }
131 if bytes.len() < ED25519_PUBLIC_KEY_LENGTH + 1 {
132 return Err(AptosError::InvalidPublicKey(format!(
133 "bytes too short: {} bytes",
134 bytes.len()
135 )));
136 }
137
138 let threshold = bytes[bytes.len() - 1];
139 let key_bytes = &bytes[..bytes.len() - 1];
140
141 if !key_bytes.len().is_multiple_of(ED25519_PUBLIC_KEY_LENGTH) {
142 return Err(AptosError::InvalidPublicKey(format!(
143 "key bytes length {} is not a multiple of {}",
144 key_bytes.len(),
145 ED25519_PUBLIC_KEY_LENGTH
146 )));
147 }
148
149 let num_keys = key_bytes.len() / ED25519_PUBLIC_KEY_LENGTH;
150 let mut public_keys = Vec::with_capacity(num_keys);
151
152 for i in 0..num_keys {
153 let start = i * ED25519_PUBLIC_KEY_LENGTH;
154 let end = start + ED25519_PUBLIC_KEY_LENGTH;
155 let pk = Ed25519PublicKey::from_bytes(&key_bytes[start..end])?;
156 public_keys.push(pk);
157 }
158
159 Self::new(public_keys, threshold)
160 }
161
162 pub fn to_address(&self) -> crate::types::AccountAddress {
164 crate::crypto::derive_address(&self.to_bytes(), crate::crypto::MULTI_ED25519_SCHEME)
165 }
166
167 pub fn to_authentication_key(&self) -> [u8; 32] {
169 crate::crypto::derive_authentication_key(
170 &self.to_bytes(),
171 crate::crypto::MULTI_ED25519_SCHEME,
172 )
173 }
174
175 pub fn verify(&self, message: &[u8], signature: &MultiEd25519Signature) -> AptosResult<()> {
184 if signature.num_signatures() < self.threshold as usize {
186 return Err(AptosError::SignatureVerificationFailed);
187 }
188
189 for (index, sig) in signature.signatures() {
191 if *index as usize >= self.public_keys.len() {
192 return Err(AptosError::InvalidSignature(format!(
193 "signer index {} out of bounds (max {})",
194 index,
195 self.public_keys.len() - 1
196 )));
197 }
198 let pk = &self.public_keys[*index as usize];
199 pk.verify(message, sig)?;
200 }
201
202 Ok(())
203 }
204}
205
206impl PublicKey for MultiEd25519PublicKey {
207 const LENGTH: usize = 0; fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
210 MultiEd25519PublicKey::from_bytes(bytes)
211 }
212
213 fn to_bytes(&self) -> Vec<u8> {
214 MultiEd25519PublicKey::to_bytes(self)
215 }
216}
217
218impl Verifier for MultiEd25519PublicKey {
219 type Signature = MultiEd25519Signature;
220
221 fn verify(&self, message: &[u8], signature: &MultiEd25519Signature) -> AptosResult<()> {
222 MultiEd25519PublicKey::verify(self, message, signature)
223 }
224}
225
226impl fmt::Debug for MultiEd25519PublicKey {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 write!(
229 f,
230 "MultiEd25519PublicKey({}-of-{} keys)",
231 self.threshold,
232 self.public_keys.len()
233 )
234 }
235}
236
237impl fmt::Display for MultiEd25519PublicKey {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
240 }
241}
242
243impl Serialize for MultiEd25519PublicKey {
244 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
245 where
246 S: serde::Serializer,
247 {
248 if serializer.is_human_readable() {
249 serializer.serialize_str(&const_hex::encode_prefixed(self.to_bytes()))
250 } else {
251 serializer.serialize_bytes(&self.to_bytes())
252 }
253 }
254}
255
256impl<'de> Deserialize<'de> for MultiEd25519PublicKey {
257 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
258 where
259 D: serde::Deserializer<'de>,
260 {
261 if deserializer.is_human_readable() {
262 let bytes: Vec<u8> = const_hex::deserialize(deserializer)?;
263 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
264 } else {
265 let bytes = Vec::<u8>::deserialize(deserializer)?;
266 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
267 }
268 }
269}
270
271#[derive(Clone, PartialEq, Eq)]
276pub struct MultiEd25519Signature {
277 signatures: Vec<(u8, Ed25519Signature)>,
279 bitmap: [u8; 4],
284}
285
286impl MultiEd25519Signature {
287 pub fn new(mut signatures: Vec<(u8, Ed25519Signature)>) -> AptosResult<Self> {
303 if signatures.is_empty() {
304 return Err(AptosError::InvalidSignature(
305 "multi-Ed25519 signature requires at least one signature".into(),
306 ));
307 }
308 if signatures.len() > MAX_NUM_OF_KEYS {
309 return Err(AptosError::InvalidSignature(format!(
310 "too many signatures: {} (max {})",
311 signatures.len(),
312 MAX_NUM_OF_KEYS
313 )));
314 }
315
316 signatures.sort_by_key(|(idx, _)| *idx);
318
319 let mut bitmap = [0u8; 4];
321 let mut last_index: Option<u8> = None;
322
323 for (index, _) in &signatures {
324 if *index as usize >= MAX_NUM_OF_KEYS {
325 return Err(AptosError::InvalidSignature(format!(
326 "signer index {} out of bounds (max {})",
327 index,
328 MAX_NUM_OF_KEYS - 1
329 )));
330 }
331 if last_index == Some(*index) {
332 return Err(AptosError::InvalidSignature(format!(
333 "duplicate signer index {index}"
334 )));
335 }
336 last_index = Some(*index);
337
338 let byte_index = (index / 8) as usize;
346 let bit_index_in_byte = index % 8;
347 bitmap[byte_index] |= 128u8 >> bit_index_in_byte;
348 }
349
350 Ok(Self { signatures, bitmap })
351 }
352
353 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
364 if bytes.len() < 4 {
365 return Err(AptosError::InvalidSignature("bytes too short".into()));
366 }
367
368 let bitmap_start = bytes.len() - 4;
369 let mut bitmap = [0u8; 4];
370 bitmap.copy_from_slice(&bytes[bitmap_start..]);
371
372 let sig_bytes = &bytes[..bitmap_start];
373
374 let num_sigs = bitmap.iter().map(|b| b.count_ones()).sum::<u32>() as usize;
376
377 if sig_bytes.len() != num_sigs * ED25519_SIGNATURE_LENGTH {
378 return Err(AptosError::InvalidSignature(format!(
379 "signature bytes length {} doesn't match expected {} signatures",
380 sig_bytes.len(),
381 num_sigs
382 )));
383 }
384
385 let mut signatures = Vec::with_capacity(num_sigs);
388 let mut sig_idx = 0;
389
390 #[allow(clippy::cast_possible_truncation)]
391 for bit_pos in 0..(MAX_NUM_OF_KEYS as u8) {
392 let byte_idx = (bit_pos / 8) as usize;
393 let bit_in_byte = bit_pos % 8;
394
395 if (bitmap[byte_idx] & (128u8 >> bit_in_byte)) != 0 {
396 let start = sig_idx * ED25519_SIGNATURE_LENGTH;
397 let end = start + ED25519_SIGNATURE_LENGTH;
398 let sig = Ed25519Signature::from_bytes(&sig_bytes[start..end])?;
399 signatures.push((bit_pos, sig));
400 sig_idx += 1;
401 }
402 }
403
404 Ok(Self { signatures, bitmap })
405 }
406
407 pub fn to_bytes(&self) -> Vec<u8> {
409 let mut bytes = Vec::with_capacity(self.signatures.len() * ED25519_SIGNATURE_LENGTH + 4);
410 for (_, sig) in &self.signatures {
411 bytes.extend_from_slice(&sig.to_bytes());
412 }
413 bytes.extend_from_slice(&self.bitmap);
414 bytes
415 }
416
417 pub fn num_signatures(&self) -> usize {
419 self.signatures.len()
420 }
421
422 pub fn signatures(&self) -> &[(u8, Ed25519Signature)] {
424 &self.signatures
425 }
426
427 pub fn bitmap(&self) -> &[u8; 4] {
429 &self.bitmap
430 }
431
432 pub fn has_signature(&self, index: u8) -> bool {
434 if index as usize >= MAX_NUM_OF_KEYS {
435 return false;
436 }
437 let byte_index = (index / 8) as usize;
438 let bit_in_byte = index % 8;
439 (self.bitmap[byte_index] & (128u8 >> bit_in_byte)) != 0
440 }
441}
442
443impl crate::crypto::traits::Signature for MultiEd25519Signature {
444 type PublicKey = MultiEd25519PublicKey;
445 const LENGTH: usize = 0; fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
448 MultiEd25519Signature::from_bytes(bytes)
449 }
450
451 fn to_bytes(&self) -> Vec<u8> {
452 MultiEd25519Signature::to_bytes(self)
453 }
454}
455
456impl fmt::Debug for MultiEd25519Signature {
457 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
458 write!(
459 f,
460 "MultiEd25519Signature({} signatures, bitmap={:?})",
461 self.signatures.len(),
462 self.bitmap
463 )
464 }
465}
466
467impl fmt::Display for MultiEd25519Signature {
468 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
470 }
471}
472
473impl Serialize for MultiEd25519Signature {
474 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
475 where
476 S: serde::Serializer,
477 {
478 if serializer.is_human_readable() {
479 serializer.serialize_str(&const_hex::encode_prefixed(self.to_bytes()))
480 } else {
481 serializer.serialize_bytes(&self.to_bytes())
482 }
483 }
484}
485
486impl<'de> Deserialize<'de> for MultiEd25519Signature {
487 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
488 where
489 D: serde::Deserializer<'de>,
490 {
491 if deserializer.is_human_readable() {
492 let bytes: Vec<u8> = const_hex::deserialize(deserializer)?;
493 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
494 } else {
495 let bytes = Vec::<u8>::deserialize(deserializer)?;
496 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
497 }
498 }
499}
500
501#[cfg(test)]
502mod tests {
503 use super::*;
504 use crate::crypto::Ed25519PrivateKey;
505
506 #[test]
507 fn test_multi_ed25519_public_key_creation() {
508 let keys: Vec<_> = (0..3)
509 .map(|_| Ed25519PrivateKey::generate().public_key())
510 .collect();
511
512 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
514 assert_eq!(multi_pk.num_keys(), 3);
515 assert_eq!(multi_pk.threshold(), 2);
516
517 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 3).unwrap();
519 assert_eq!(multi_pk.threshold(), 3);
520
521 assert!(MultiEd25519PublicKey::new(keys.clone(), 4).is_err());
523
524 assert!(MultiEd25519PublicKey::new(keys.clone(), 0).is_err());
526
527 assert!(MultiEd25519PublicKey::new(vec![], 1).is_err());
529 }
530
531 #[test]
532 fn test_multi_ed25519_sign_verify() {
533 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
534 let public_keys: Vec<_> = private_keys
535 .iter()
536 .map(Ed25519PrivateKey::public_key)
537 .collect();
538
539 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
540 let message = b"test message";
541
542 let sig0 = private_keys[0].sign(message);
544 let sig2 = private_keys[2].sign(message);
545
546 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
547
548 assert!(multi_pk.verify(message, &multi_sig).is_ok());
550
551 assert!(multi_pk.verify(b"wrong message", &multi_sig).is_err());
553 }
554
555 #[test]
556 fn test_multi_ed25519_insufficient_signatures() {
557 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
558 let public_keys: Vec<_> = private_keys
559 .iter()
560 .map(Ed25519PrivateKey::public_key)
561 .collect();
562
563 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
564 let message = b"test message";
565
566 let sig0 = private_keys[0].sign(message);
568 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0)]).unwrap();
569
570 assert!(multi_pk.verify(message, &multi_sig).is_err());
572 }
573
574 #[test]
575 fn test_multi_ed25519_bytes_roundtrip() {
576 let keys: Vec<_> = (0..3)
577 .map(|_| Ed25519PrivateKey::generate().public_key())
578 .collect();
579 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
580
581 let bytes = multi_pk.to_bytes();
582 let restored = MultiEd25519PublicKey::from_bytes(&bytes).unwrap();
583
584 assert_eq!(multi_pk.threshold(), restored.threshold());
585 assert_eq!(multi_pk.num_keys(), restored.num_keys());
586 assert_eq!(multi_pk.to_bytes(), restored.to_bytes());
587 }
588
589 #[test]
590 fn test_multi_ed25519_signature_bytes_roundtrip() {
591 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
592 let message = b"test";
593
594 let sig0 = private_keys[0].sign(message);
595 let sig2 = private_keys[2].sign(message);
596
597 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
598
599 let bytes = multi_sig.to_bytes();
600 let restored = MultiEd25519Signature::from_bytes(&bytes).unwrap();
601
602 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
603 assert_eq!(multi_sig.bitmap(), restored.bitmap());
604 }
605
606 #[test]
607 fn test_multi_ed25519_address_derivation() {
608 let keys: Vec<_> = (0..3)
609 .map(|_| Ed25519PrivateKey::generate().public_key())
610 .collect();
611 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
612
613 let address = multi_pk.to_address();
614 assert!(!address.is_zero());
615
616 let address2 = multi_pk.to_address();
618 assert_eq!(address, address2);
619 }
620
621 #[test]
622 fn test_signature_bitmap() {
623 let private_keys: Vec<_> = (0..5).map(|_| Ed25519PrivateKey::generate()).collect();
624 let message = b"test";
625
626 let signatures: Vec<_> = [1, 3, 4]
628 .iter()
629 .map(|&i| (i, private_keys[i as usize].sign(message)))
630 .collect();
631
632 let multi_sig = MultiEd25519Signature::new(signatures).unwrap();
633
634 assert!(!multi_sig.has_signature(0));
635 assert!(multi_sig.has_signature(1));
636 assert!(!multi_sig.has_signature(2));
637 assert!(multi_sig.has_signature(3));
638 assert!(multi_sig.has_signature(4));
639 assert!(!multi_sig.has_signature(5));
640 }
641
642 #[test]
643 fn test_multi_ed25519_public_key_too_many_keys() {
644 let keys: Vec<_> = (0..33) .map(|_| Ed25519PrivateKey::generate().public_key())
646 .collect();
647
648 let result = MultiEd25519PublicKey::new(keys, 2);
649 assert!(result.is_err());
650 }
651
652 #[test]
653 fn test_multi_ed25519_public_keys_accessor() {
654 let keys: Vec<_> = (0..3)
655 .map(|_| Ed25519PrivateKey::generate().public_key())
656 .collect();
657 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
658
659 assert_eq!(multi_pk.public_keys().len(), 3);
660 }
661
662 #[test]
663 fn test_multi_ed25519_signature_num_signatures() {
664 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
665 let message = b"test";
666
667 let sig0 = private_keys[0].sign(message);
668 let sig2 = private_keys[2].sign(message);
669
670 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
671
672 assert_eq!(multi_sig.num_signatures(), 2);
673 let bitmap_bytes = multi_sig.bitmap();
676 assert_eq!(bitmap_bytes[0], 0b1010_0000);
677 }
678
679 #[test]
680 fn test_multi_ed25519_signature_empty() {
681 let result = MultiEd25519Signature::new(vec![]);
682 assert!(result.is_err());
683 }
684
685 #[test]
686 fn test_multi_ed25519_signature_index_out_of_bounds() {
687 let private_key = Ed25519PrivateKey::generate();
688 let sig = private_key.sign(b"test");
689
690 let result = MultiEd25519Signature::new(vec![(33, sig)]);
692 assert!(result.is_err());
693 }
694
695 #[test]
696 fn test_multi_ed25519_signature_duplicate_index() {
697 let private_key = Ed25519PrivateKey::generate();
698 let sig1 = private_key.sign(b"test1");
699 let sig2 = private_key.sign(b"test2");
700
701 let result = MultiEd25519Signature::new(vec![(0, sig1), (0, sig2)]);
703 assert!(result.is_err());
704 }
705
706 #[test]
707 fn test_multi_ed25519_public_key_from_bytes_invalid() {
708 let result = MultiEd25519PublicKey::from_bytes(&[]);
710 assert!(result.is_err());
711
712 let result = MultiEd25519PublicKey::from_bytes(&[2]);
714 assert!(result.is_err());
715
716 let result = MultiEd25519PublicKey::from_bytes(&[1, 2, 3, 4, 5]);
718 assert!(result.is_err());
719 }
720
721 #[test]
722 fn test_multi_ed25519_signature_from_bytes_invalid() {
723 let result = MultiEd25519Signature::from_bytes(&[]);
725 assert!(result.is_err());
726
727 let result = MultiEd25519Signature::from_bytes(&[0, 0, 0, 1]);
729 assert!(result.is_err());
730 }
731
732 #[test]
733 fn test_multi_ed25519_verify_invalid_signature_index() {
734 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
735 let public_keys: Vec<_> = private_keys
736 .iter()
737 .map(Ed25519PrivateKey::public_key)
738 .collect();
739
740 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
741 let message = b"test message";
742
743 let sig0 = private_keys[0].sign(message);
745 let sig5 = private_keys[0].sign(message); let bitmap = (1u32 << 0) | (1u32 << 5);
749 let mut bytes = Vec::new();
750 bytes.extend_from_slice(&sig0.to_bytes());
751 bytes.extend_from_slice(&sig5.to_bytes());
752 bytes.extend_from_slice(&bitmap.to_le_bytes());
753
754 let multi_sig = MultiEd25519Signature::from_bytes(&bytes).unwrap();
755
756 let result = multi_pk.verify(message, &multi_sig);
758 assert!(result.is_err());
759 }
760
761 #[test]
762 fn test_multi_ed25519_verify_wrong_signature() {
763 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
764 let public_keys: Vec<_> = private_keys
765 .iter()
766 .map(Ed25519PrivateKey::public_key)
767 .collect();
768
769 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
770 let message = b"test message";
771
772 let sig0 = private_keys[0].sign(message);
774 let sig1 = private_keys[0].sign(message); let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
777
778 let result = multi_pk.verify(message, &multi_sig);
780 assert!(result.is_err());
781 }
782
783 #[test]
784 fn test_multi_ed25519_public_key_debug() {
785 let keys: Vec<_> = (0..2)
786 .map(|_| Ed25519PrivateKey::generate().public_key())
787 .collect();
788 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
789 let debug = format!("{multi_pk:?}");
790 assert!(debug.contains("MultiEd25519PublicKey"));
791 assert!(debug.contains("2-of-2"));
792 }
793
794 #[test]
795 fn test_multi_ed25519_signature_debug() {
796 let private_key = Ed25519PrivateKey::generate();
797 let sig = private_key.sign(b"test");
798 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
799
800 let debug = format!("{multi_sig:?}");
801 assert!(debug.contains("MultiEd25519Signature"));
802 }
803
804 #[test]
805 fn test_multi_ed25519_json_serialization() {
806 let keys: Vec<_> = (0..3)
807 .map(|_| Ed25519PrivateKey::generate().public_key())
808 .collect();
809 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
810
811 let json = serde_json::to_string(&multi_pk).unwrap();
812 let parsed: MultiEd25519PublicKey = serde_json::from_str(&json).unwrap();
813
814 assert_eq!(multi_pk.threshold(), parsed.threshold());
815 assert_eq!(multi_pk.num_keys(), parsed.num_keys());
816 }
817
818 #[test]
819 fn test_multi_ed25519_signature_json_serialization() {
820 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
821 let message = b"test";
822
823 let sig0 = private_keys[0].sign(message);
824 let sig2 = private_keys[2].sign(message);
825
826 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
827
828 let json = serde_json::to_string(&multi_sig).unwrap();
829 let parsed: MultiEd25519Signature = serde_json::from_str(&json).unwrap();
830
831 assert_eq!(multi_sig.num_signatures(), parsed.num_signatures());
832 assert_eq!(multi_sig.bitmap(), parsed.bitmap());
833 }
834
835 #[test]
836 fn test_multi_ed25519_signature_from_bytes_too_short() {
837 let bytes = vec![0u8; 3]; let result = MultiEd25519Signature::from_bytes(&bytes);
839 assert!(result.is_err());
840 assert!(result.unwrap_err().to_string().contains("too short"));
841 }
842
843 #[test]
844 fn test_multi_ed25519_signature_from_bytes_invalid_length() {
845 let mut bytes = vec![0u8; 10]; bytes.extend_from_slice(&[0x01, 0x00, 0x00, 0x00]);
849
850 let result = MultiEd25519Signature::from_bytes(&bytes);
851 assert!(result.is_err());
852 }
853
854 #[test]
855 fn test_multi_ed25519_signature_has_signature() {
856 let private_key = Ed25519PrivateKey::generate();
857 let sig0 = private_key.sign(b"test");
858 let sig2 = private_key.sign(b"test");
859
860 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
861
862 assert!(multi_sig.has_signature(0));
863 assert!(!multi_sig.has_signature(1));
864 assert!(multi_sig.has_signature(2));
865 assert!(!multi_sig.has_signature(3));
866 assert!(!multi_sig.has_signature(32)); }
868
869 #[test]
870 fn test_multi_ed25519_signature_signatures_accessor() {
871 let private_key = Ed25519PrivateKey::generate();
872 let sig0 = private_key.sign(b"test");
873 let sig1 = private_key.sign(b"test");
874
875 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
876
877 let signatures = multi_sig.signatures();
878 assert_eq!(signatures.len(), 2);
879 assert_eq!(signatures[0].0, 0);
880 assert_eq!(signatures[1].0, 1);
881 }
882
883 #[test]
884 fn test_multi_ed25519_public_key_public_keys_accessor() {
885 let keys: Vec<_> = (0..3)
886 .map(|_| Ed25519PrivateKey::generate().public_key())
887 .collect();
888 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
889
890 let pks = multi_pk.public_keys();
891 assert_eq!(pks.len(), 3);
892 }
893
894 #[test]
895 fn test_multi_ed25519_signature_display() {
896 let private_key = Ed25519PrivateKey::generate();
897 let sig = private_key.sign(b"test");
898 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
899
900 let display = format!("{multi_sig}");
901 assert!(display.starts_with("0x"));
902 }
903
904 #[test]
905 fn test_multi_ed25519_public_key_display() {
906 let keys: Vec<_> = (0..2)
907 .map(|_| Ed25519PrivateKey::generate().public_key())
908 .collect();
909 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
910
911 let display = format!("{multi_pk}");
912 assert!(display.starts_with("0x"));
913 }
914
915 #[test]
916 fn test_multi_ed25519_signature_roundtrip() {
917 let private_key = Ed25519PrivateKey::generate();
918 let sig0 = private_key.sign(b"test");
919 let sig1 = private_key.sign(b"test");
920
921 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
922 let bytes = multi_sig.to_bytes();
923 let restored = MultiEd25519Signature::from_bytes(&bytes).unwrap();
924
925 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
926 assert_eq!(multi_sig.bitmap(), restored.bitmap());
927 }
928
929 #[test]
930 fn test_multi_ed25519_public_key_roundtrip() {
931 let keys: Vec<_> = (0..3)
932 .map(|_| Ed25519PrivateKey::generate().public_key())
933 .collect();
934 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
935 let bytes = multi_pk.to_bytes();
936 let restored = MultiEd25519PublicKey::from_bytes(&bytes).unwrap();
937
938 assert_eq!(multi_pk.threshold(), restored.threshold());
939 assert_eq!(multi_pk.num_keys(), restored.num_keys());
940 }
941
942 #[test]
943 fn test_multi_ed25519_signature_new_empty() {
944 let result = MultiEd25519Signature::new(vec![]);
945 assert!(result.is_err());
946 assert!(result.unwrap_err().to_string().contains("at least one"));
947 }
948
949 #[test]
950 fn test_multi_ed25519_signature_new_duplicate_index() {
951 let private_key = Ed25519PrivateKey::generate();
952 let first_sig = private_key.sign(b"test");
953 let second_sig = private_key.sign(b"test");
954
955 let result = MultiEd25519Signature::new(vec![(0, first_sig), (0, second_sig)]);
956 assert!(result.is_err());
957 assert!(result.unwrap_err().to_string().contains("duplicate"));
958 }
959
960 #[test]
961 fn test_multi_ed25519_signature_new_index_out_of_bounds() {
962 let private_key = Ed25519PrivateKey::generate();
963 let sig = private_key.sign(b"test");
964
965 let result = MultiEd25519Signature::new(vec![(32, sig)]); assert!(result.is_err());
967 }
968
969 #[test]
970 fn test_multi_ed25519_public_key_to_address() {
971 let keys: Vec<_> = (0..3)
972 .map(|_| Ed25519PrivateKey::generate().public_key())
973 .collect();
974 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
975
976 let address = multi_pk.to_address();
977 assert!(!address.is_zero());
978 }
979
980 #[test]
981 fn test_multi_ed25519_public_key_from_bytes_invalid_length() {
982 let bytes = vec![0u8; 10];
984 let result = MultiEd25519PublicKey::from_bytes(&bytes);
985 assert!(result.is_err());
986 }
987
988 #[test]
989 fn test_multi_ed25519_bcs_roundtrip_public_key() {
990 let keys: Vec<_> = (0..3)
991 .map(|_| Ed25519PrivateKey::generate().public_key())
992 .collect();
993 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
994
995 let bcs_bytes = aptos_bcs::to_bytes(&multi_pk).unwrap();
996 let restored: MultiEd25519PublicKey = aptos_bcs::from_bytes(&bcs_bytes).unwrap();
997
998 assert_eq!(multi_pk.threshold(), restored.threshold());
999 assert_eq!(multi_pk.num_keys(), restored.num_keys());
1000 }
1001
1002 #[test]
1003 fn test_multi_ed25519_bcs_roundtrip_signature() {
1004 let private_key = Ed25519PrivateKey::generate();
1005 let sig = private_key.sign(b"test");
1006 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
1007
1008 let bcs_bytes = aptos_bcs::to_bytes(&multi_sig).unwrap();
1009 let restored: MultiEd25519Signature = aptos_bcs::from_bytes(&bcs_bytes).unwrap();
1010
1011 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
1012 }
1013}