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],
281}
282
283impl MultiEd25519Signature {
284 pub fn new(mut signatures: Vec<(u8, Ed25519Signature)>) -> AptosResult<Self> {
300 if signatures.is_empty() {
301 return Err(AptosError::InvalidSignature(
302 "multi-Ed25519 signature requires at least one signature".into(),
303 ));
304 }
305 if signatures.len() > MAX_NUM_OF_KEYS {
306 return Err(AptosError::InvalidSignature(format!(
307 "too many signatures: {} (max {})",
308 signatures.len(),
309 MAX_NUM_OF_KEYS
310 )));
311 }
312
313 signatures.sort_by_key(|(idx, _)| *idx);
315
316 let mut bitmap = [0u8; 4];
318 let mut last_index: Option<u8> = None;
319
320 for (index, _) in &signatures {
321 if *index as usize >= MAX_NUM_OF_KEYS {
322 return Err(AptosError::InvalidSignature(format!(
323 "signer index {} out of bounds (max {})",
324 index,
325 MAX_NUM_OF_KEYS - 1
326 )));
327 }
328 if last_index == Some(*index) {
329 return Err(AptosError::InvalidSignature(format!(
330 "duplicate signer index {index}"
331 )));
332 }
333 last_index = Some(*index);
334
335 let byte_index = (index / 8) as usize;
343 let bit_index_in_byte = index % 8;
344 bitmap[byte_index] |= 128u8 >> bit_index_in_byte;
345 }
346
347 Ok(Self { signatures, bitmap })
348 }
349
350 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
361 if bytes.len() < 4 {
362 return Err(AptosError::InvalidSignature("bytes too short".into()));
363 }
364
365 let bitmap_start = bytes.len() - 4;
366 let mut bitmap = [0u8; 4];
367 bitmap.copy_from_slice(&bytes[bitmap_start..]);
368
369 let sig_bytes = &bytes[..bitmap_start];
370
371 let num_sigs = bitmap.iter().map(|b| b.count_ones()).sum::<u32>() as usize;
373
374 if sig_bytes.len() != num_sigs * ED25519_SIGNATURE_LENGTH {
375 return Err(AptosError::InvalidSignature(format!(
376 "signature bytes length {} doesn't match expected {} signatures",
377 sig_bytes.len(),
378 num_sigs
379 )));
380 }
381
382 let mut signatures = Vec::with_capacity(num_sigs);
385 let mut sig_idx = 0;
386
387 #[allow(clippy::cast_possible_truncation)]
388 for bit_pos in 0..(MAX_NUM_OF_KEYS as u8) {
389 let byte_idx = (bit_pos / 8) as usize;
390 let bit_in_byte = bit_pos % 8;
391
392 if (bitmap[byte_idx] & (128u8 >> bit_in_byte)) != 0 {
393 let start = sig_idx * ED25519_SIGNATURE_LENGTH;
394 let end = start + ED25519_SIGNATURE_LENGTH;
395 let sig = Ed25519Signature::from_bytes(&sig_bytes[start..end])?;
396 signatures.push((bit_pos, sig));
397 sig_idx += 1;
398 }
399 }
400
401 Ok(Self { signatures, bitmap })
402 }
403
404 pub fn to_bytes(&self) -> Vec<u8> {
406 let mut bytes = Vec::with_capacity(self.signatures.len() * ED25519_SIGNATURE_LENGTH + 4);
407 for (_, sig) in &self.signatures {
408 bytes.extend_from_slice(&sig.to_bytes());
409 }
410 bytes.extend_from_slice(&self.bitmap);
411 bytes
412 }
413
414 pub fn num_signatures(&self) -> usize {
416 self.signatures.len()
417 }
418
419 pub fn signatures(&self) -> &[(u8, Ed25519Signature)] {
421 &self.signatures
422 }
423
424 pub fn bitmap(&self) -> &[u8; 4] {
426 &self.bitmap
427 }
428
429 pub fn has_signature(&self, index: u8) -> bool {
431 if index as usize >= MAX_NUM_OF_KEYS {
432 return false;
433 }
434 let byte_index = (index / 8) as usize;
435 let bit_in_byte = index % 8;
436 (self.bitmap[byte_index] & (128u8 >> bit_in_byte)) != 0
437 }
438}
439
440impl crate::crypto::traits::Signature for MultiEd25519Signature {
441 type PublicKey = MultiEd25519PublicKey;
442 const LENGTH: usize = 0; fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
445 MultiEd25519Signature::from_bytes(bytes)
446 }
447
448 fn to_bytes(&self) -> Vec<u8> {
449 MultiEd25519Signature::to_bytes(self)
450 }
451}
452
453impl fmt::Debug for MultiEd25519Signature {
454 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455 write!(
456 f,
457 "MultiEd25519Signature({} signatures, bitmap={:?})",
458 self.signatures.len(),
459 self.bitmap
460 )
461 }
462}
463
464impl fmt::Display for MultiEd25519Signature {
465 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
466 f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
467 }
468}
469
470impl Serialize for MultiEd25519Signature {
471 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
472 where
473 S: serde::Serializer,
474 {
475 if serializer.is_human_readable() {
476 serializer.serialize_str(&const_hex::encode_prefixed(self.to_bytes()))
477 } else {
478 serializer.serialize_bytes(&self.to_bytes())
479 }
480 }
481}
482
483impl<'de> Deserialize<'de> for MultiEd25519Signature {
484 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
485 where
486 D: serde::Deserializer<'de>,
487 {
488 if deserializer.is_human_readable() {
489 let bytes: Vec<u8> = const_hex::deserialize(deserializer)?;
490 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
491 } else {
492 let bytes = Vec::<u8>::deserialize(deserializer)?;
493 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
494 }
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501 use crate::crypto::Ed25519PrivateKey;
502
503 #[test]
504 fn test_multi_ed25519_public_key_creation() {
505 let keys: Vec<_> = (0..3)
506 .map(|_| Ed25519PrivateKey::generate().public_key())
507 .collect();
508
509 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
511 assert_eq!(multi_pk.num_keys(), 3);
512 assert_eq!(multi_pk.threshold(), 2);
513
514 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 3).unwrap();
516 assert_eq!(multi_pk.threshold(), 3);
517
518 assert!(MultiEd25519PublicKey::new(keys.clone(), 4).is_err());
520
521 assert!(MultiEd25519PublicKey::new(keys.clone(), 0).is_err());
523
524 assert!(MultiEd25519PublicKey::new(vec![], 1).is_err());
526 }
527
528 #[test]
529 fn test_multi_ed25519_sign_verify() {
530 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
531 let public_keys: Vec<_> = private_keys
532 .iter()
533 .map(Ed25519PrivateKey::public_key)
534 .collect();
535
536 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
537 let message = b"test message";
538
539 let sig0 = private_keys[0].sign(message);
541 let sig2 = private_keys[2].sign(message);
542
543 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
544
545 assert!(multi_pk.verify(message, &multi_sig).is_ok());
547
548 assert!(multi_pk.verify(b"wrong message", &multi_sig).is_err());
550 }
551
552 #[test]
553 fn test_multi_ed25519_insufficient_signatures() {
554 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
555 let public_keys: Vec<_> = private_keys
556 .iter()
557 .map(Ed25519PrivateKey::public_key)
558 .collect();
559
560 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
561 let message = b"test message";
562
563 let sig0 = private_keys[0].sign(message);
565 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0)]).unwrap();
566
567 assert!(multi_pk.verify(message, &multi_sig).is_err());
569 }
570
571 #[test]
572 fn test_multi_ed25519_bytes_roundtrip() {
573 let keys: Vec<_> = (0..3)
574 .map(|_| Ed25519PrivateKey::generate().public_key())
575 .collect();
576 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
577
578 let bytes = multi_pk.to_bytes();
579 let restored = MultiEd25519PublicKey::from_bytes(&bytes).unwrap();
580
581 assert_eq!(multi_pk.threshold(), restored.threshold());
582 assert_eq!(multi_pk.num_keys(), restored.num_keys());
583 assert_eq!(multi_pk.to_bytes(), restored.to_bytes());
584 }
585
586 #[test]
587 fn test_multi_ed25519_signature_bytes_roundtrip() {
588 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
589 let message = b"test";
590
591 let sig0 = private_keys[0].sign(message);
592 let sig2 = private_keys[2].sign(message);
593
594 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
595
596 let bytes = multi_sig.to_bytes();
597 let restored = MultiEd25519Signature::from_bytes(&bytes).unwrap();
598
599 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
600 assert_eq!(multi_sig.bitmap(), restored.bitmap());
601 }
602
603 #[test]
604 fn test_multi_ed25519_address_derivation() {
605 let keys: Vec<_> = (0..3)
606 .map(|_| Ed25519PrivateKey::generate().public_key())
607 .collect();
608 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
609
610 let address = multi_pk.to_address();
611 assert!(!address.is_zero());
612
613 let address2 = multi_pk.to_address();
615 assert_eq!(address, address2);
616 }
617
618 #[test]
619 fn test_signature_bitmap() {
620 let private_keys: Vec<_> = (0..5).map(|_| Ed25519PrivateKey::generate()).collect();
621 let message = b"test";
622
623 let signatures: Vec<_> = [1, 3, 4]
625 .iter()
626 .map(|&i| (i, private_keys[i as usize].sign(message)))
627 .collect();
628
629 let multi_sig = MultiEd25519Signature::new(signatures).unwrap();
630
631 assert!(!multi_sig.has_signature(0));
632 assert!(multi_sig.has_signature(1));
633 assert!(!multi_sig.has_signature(2));
634 assert!(multi_sig.has_signature(3));
635 assert!(multi_sig.has_signature(4));
636 assert!(!multi_sig.has_signature(5));
637 }
638
639 #[test]
640 fn test_multi_ed25519_public_key_too_many_keys() {
641 let keys: Vec<_> = (0..33) .map(|_| Ed25519PrivateKey::generate().public_key())
643 .collect();
644
645 let result = MultiEd25519PublicKey::new(keys, 2);
646 assert!(result.is_err());
647 }
648
649 #[test]
650 fn test_multi_ed25519_public_keys_accessor() {
651 let keys: Vec<_> = (0..3)
652 .map(|_| Ed25519PrivateKey::generate().public_key())
653 .collect();
654 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
655
656 assert_eq!(multi_pk.public_keys().len(), 3);
657 }
658
659 #[test]
660 fn test_multi_ed25519_signature_num_signatures() {
661 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
662 let message = b"test";
663
664 let sig0 = private_keys[0].sign(message);
665 let sig2 = private_keys[2].sign(message);
666
667 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
668
669 assert_eq!(multi_sig.num_signatures(), 2);
670 let bitmap_bytes = multi_sig.bitmap();
673 assert_eq!(bitmap_bytes[0], 0b1010_0000);
674 }
675
676 #[test]
677 fn test_multi_ed25519_signature_empty() {
678 let result = MultiEd25519Signature::new(vec![]);
679 assert!(result.is_err());
680 }
681
682 #[test]
683 fn test_multi_ed25519_signature_index_out_of_bounds() {
684 let private_key = Ed25519PrivateKey::generate();
685 let sig = private_key.sign(b"test");
686
687 let result = MultiEd25519Signature::new(vec![(33, sig)]);
689 assert!(result.is_err());
690 }
691
692 #[test]
693 fn test_multi_ed25519_signature_duplicate_index() {
694 let private_key = Ed25519PrivateKey::generate();
695 let sig1 = private_key.sign(b"test1");
696 let sig2 = private_key.sign(b"test2");
697
698 let result = MultiEd25519Signature::new(vec![(0, sig1), (0, sig2)]);
700 assert!(result.is_err());
701 }
702
703 #[test]
704 fn test_multi_ed25519_public_key_from_bytes_invalid() {
705 let result = MultiEd25519PublicKey::from_bytes(&[]);
707 assert!(result.is_err());
708
709 let result = MultiEd25519PublicKey::from_bytes(&[2]);
711 assert!(result.is_err());
712
713 let result = MultiEd25519PublicKey::from_bytes(&[1, 2, 3, 4, 5]);
715 assert!(result.is_err());
716 }
717
718 #[test]
719 fn test_multi_ed25519_signature_from_bytes_invalid() {
720 let result = MultiEd25519Signature::from_bytes(&[]);
722 assert!(result.is_err());
723
724 let result = MultiEd25519Signature::from_bytes(&[0, 0, 0, 1]);
726 assert!(result.is_err());
727 }
728
729 #[test]
730 fn test_multi_ed25519_verify_invalid_signature_index() {
731 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
732 let public_keys: Vec<_> = private_keys
733 .iter()
734 .map(Ed25519PrivateKey::public_key)
735 .collect();
736
737 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
738 let message = b"test message";
739
740 let sig0 = private_keys[0].sign(message);
742 let sig5 = private_keys[0].sign(message); let bitmap = (1u32 << 0) | (1u32 << 5);
746 let mut bytes = Vec::new();
747 bytes.extend_from_slice(&sig0.to_bytes());
748 bytes.extend_from_slice(&sig5.to_bytes());
749 bytes.extend_from_slice(&bitmap.to_le_bytes());
750
751 let multi_sig = MultiEd25519Signature::from_bytes(&bytes).unwrap();
752
753 let result = multi_pk.verify(message, &multi_sig);
755 assert!(result.is_err());
756 }
757
758 #[test]
759 fn test_multi_ed25519_verify_wrong_signature() {
760 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
761 let public_keys: Vec<_> = private_keys
762 .iter()
763 .map(Ed25519PrivateKey::public_key)
764 .collect();
765
766 let multi_pk = MultiEd25519PublicKey::new(public_keys, 2).unwrap();
767 let message = b"test message";
768
769 let sig0 = private_keys[0].sign(message);
771 let sig1 = private_keys[0].sign(message); let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
774
775 let result = multi_pk.verify(message, &multi_sig);
777 assert!(result.is_err());
778 }
779
780 #[test]
781 fn test_multi_ed25519_public_key_debug() {
782 let keys: Vec<_> = (0..2)
783 .map(|_| Ed25519PrivateKey::generate().public_key())
784 .collect();
785 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
786 let debug = format!("{multi_pk:?}");
787 assert!(debug.contains("MultiEd25519PublicKey"));
788 assert!(debug.contains("2-of-2"));
789 }
790
791 #[test]
792 fn test_multi_ed25519_signature_debug() {
793 let private_key = Ed25519PrivateKey::generate();
794 let sig = private_key.sign(b"test");
795 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
796
797 let debug = format!("{multi_sig:?}");
798 assert!(debug.contains("MultiEd25519Signature"));
799 }
800
801 #[test]
802 fn test_multi_ed25519_json_serialization() {
803 let keys: Vec<_> = (0..3)
804 .map(|_| Ed25519PrivateKey::generate().public_key())
805 .collect();
806 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
807
808 let json = serde_json::to_string(&multi_pk).unwrap();
809 let parsed: MultiEd25519PublicKey = serde_json::from_str(&json).unwrap();
810
811 assert_eq!(multi_pk.threshold(), parsed.threshold());
812 assert_eq!(multi_pk.num_keys(), parsed.num_keys());
813 }
814
815 #[test]
816 fn test_multi_ed25519_signature_json_serialization() {
817 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
818 let message = b"test";
819
820 let sig0 = private_keys[0].sign(message);
821 let sig2 = private_keys[2].sign(message);
822
823 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
824
825 let json = serde_json::to_string(&multi_sig).unwrap();
826 let parsed: MultiEd25519Signature = serde_json::from_str(&json).unwrap();
827
828 assert_eq!(multi_sig.num_signatures(), parsed.num_signatures());
829 assert_eq!(multi_sig.bitmap(), parsed.bitmap());
830 }
831
832 #[test]
833 fn test_multi_ed25519_signature_from_bytes_too_short() {
834 let bytes = vec![0u8; 3]; let result = MultiEd25519Signature::from_bytes(&bytes);
836 assert!(result.is_err());
837 assert!(result.unwrap_err().to_string().contains("too short"));
838 }
839
840 #[test]
841 fn test_multi_ed25519_signature_from_bytes_invalid_length() {
842 let mut bytes = vec![0u8; 10]; bytes.extend_from_slice(&[0x01, 0x00, 0x00, 0x00]);
846
847 let result = MultiEd25519Signature::from_bytes(&bytes);
848 assert!(result.is_err());
849 }
850
851 #[test]
852 fn test_multi_ed25519_signature_has_signature() {
853 let private_key = Ed25519PrivateKey::generate();
854 let sig0 = private_key.sign(b"test");
855 let sig2 = private_key.sign(b"test");
856
857 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (2, sig2)]).unwrap();
858
859 assert!(multi_sig.has_signature(0));
860 assert!(!multi_sig.has_signature(1));
861 assert!(multi_sig.has_signature(2));
862 assert!(!multi_sig.has_signature(3));
863 assert!(!multi_sig.has_signature(32)); }
865
866 #[test]
867 fn test_multi_ed25519_signature_signatures_accessor() {
868 let private_key = Ed25519PrivateKey::generate();
869 let sig0 = private_key.sign(b"test");
870 let sig1 = private_key.sign(b"test");
871
872 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
873
874 let signatures = multi_sig.signatures();
875 assert_eq!(signatures.len(), 2);
876 assert_eq!(signatures[0].0, 0);
877 assert_eq!(signatures[1].0, 1);
878 }
879
880 #[test]
881 fn test_multi_ed25519_public_key_public_keys_accessor() {
882 let keys: Vec<_> = (0..3)
883 .map(|_| Ed25519PrivateKey::generate().public_key())
884 .collect();
885 let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 2).unwrap();
886
887 let pks = multi_pk.public_keys();
888 assert_eq!(pks.len(), 3);
889 }
890
891 #[test]
892 fn test_multi_ed25519_signature_display() {
893 let private_key = Ed25519PrivateKey::generate();
894 let sig = private_key.sign(b"test");
895 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
896
897 let display = format!("{multi_sig}");
898 assert!(display.starts_with("0x"));
899 }
900
901 #[test]
902 fn test_multi_ed25519_public_key_display() {
903 let keys: Vec<_> = (0..2)
904 .map(|_| Ed25519PrivateKey::generate().public_key())
905 .collect();
906 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
907
908 let display = format!("{multi_pk}");
909 assert!(display.starts_with("0x"));
910 }
911
912 #[test]
913 fn test_multi_ed25519_signature_roundtrip() {
914 let private_key = Ed25519PrivateKey::generate();
915 let sig0 = private_key.sign(b"test");
916 let sig1 = private_key.sign(b"test");
917
918 let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
919 let bytes = multi_sig.to_bytes();
920 let restored = MultiEd25519Signature::from_bytes(&bytes).unwrap();
921
922 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
923 assert_eq!(multi_sig.bitmap(), restored.bitmap());
924 }
925
926 #[test]
927 fn test_multi_ed25519_public_key_roundtrip() {
928 let keys: Vec<_> = (0..3)
929 .map(|_| Ed25519PrivateKey::generate().public_key())
930 .collect();
931 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
932 let bytes = multi_pk.to_bytes();
933 let restored = MultiEd25519PublicKey::from_bytes(&bytes).unwrap();
934
935 assert_eq!(multi_pk.threshold(), restored.threshold());
936 assert_eq!(multi_pk.num_keys(), restored.num_keys());
937 }
938
939 #[test]
940 fn test_multi_ed25519_signature_new_empty() {
941 let result = MultiEd25519Signature::new(vec![]);
942 assert!(result.is_err());
943 assert!(result.unwrap_err().to_string().contains("at least one"));
944 }
945
946 #[test]
947 fn test_multi_ed25519_signature_new_duplicate_index() {
948 let private_key = Ed25519PrivateKey::generate();
949 let first_sig = private_key.sign(b"test");
950 let second_sig = private_key.sign(b"test");
951
952 let result = MultiEd25519Signature::new(vec![(0, first_sig), (0, second_sig)]);
953 assert!(result.is_err());
954 assert!(result.unwrap_err().to_string().contains("duplicate"));
955 }
956
957 #[test]
958 fn test_multi_ed25519_signature_new_index_out_of_bounds() {
959 let private_key = Ed25519PrivateKey::generate();
960 let sig = private_key.sign(b"test");
961
962 let result = MultiEd25519Signature::new(vec![(32, sig)]); assert!(result.is_err());
964 }
965
966 #[test]
967 fn test_multi_ed25519_public_key_to_address() {
968 let keys: Vec<_> = (0..3)
969 .map(|_| Ed25519PrivateKey::generate().public_key())
970 .collect();
971 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
972
973 let address = multi_pk.to_address();
974 assert!(!address.is_zero());
975 }
976
977 #[test]
978 fn test_multi_ed25519_public_key_from_bytes_invalid_length() {
979 let bytes = vec![0u8; 10];
981 let result = MultiEd25519PublicKey::from_bytes(&bytes);
982 assert!(result.is_err());
983 }
984
985 #[test]
986 fn test_multi_ed25519_bcs_roundtrip_public_key() {
987 let keys: Vec<_> = (0..3)
988 .map(|_| Ed25519PrivateKey::generate().public_key())
989 .collect();
990 let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap();
991
992 let bcs_bytes = aptos_bcs::to_bytes(&multi_pk).unwrap();
993 let restored: MultiEd25519PublicKey = aptos_bcs::from_bytes(&bcs_bytes).unwrap();
994
995 assert_eq!(multi_pk.threshold(), restored.threshold());
996 assert_eq!(multi_pk.num_keys(), restored.num_keys());
997 }
998
999 #[test]
1000 fn test_multi_ed25519_bcs_roundtrip_signature() {
1001 let private_key = Ed25519PrivateKey::generate();
1002 let sig = private_key.sign(b"test");
1003 let multi_sig = MultiEd25519Signature::new(vec![(0, sig)]).unwrap();
1004
1005 let bcs_bytes = aptos_bcs::to_bytes(&multi_sig).unwrap();
1006 let restored: MultiEd25519Signature = aptos_bcs::from_bytes(&bcs_bytes).unwrap();
1007
1008 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
1009 }
1010}