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