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