1use crate::error::{AptosError, AptosResult};
8use serde::{Deserialize, Serialize};
9use std::fmt;
10
11pub const MAX_NUM_OF_KEYS: usize = 32;
13
14const _: () = assert!(MAX_NUM_OF_KEYS <= u8::MAX as usize);
16
17pub const MIN_THRESHOLD: u8 = 1;
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[repr(u8)]
23pub enum AnyPublicKeyVariant {
24 Ed25519 = 0,
26 Secp256k1 = 1,
28 Secp256r1 = 2,
30 Keyless = 3,
32}
33
34impl AnyPublicKeyVariant {
35 pub fn from_byte(byte: u8) -> AptosResult<Self> {
41 match byte {
42 0 => Ok(Self::Ed25519),
43 1 => Ok(Self::Secp256k1),
44 2 => Ok(Self::Secp256r1),
45 3 => Ok(Self::Keyless),
46 _ => Err(AptosError::InvalidPublicKey(format!(
47 "unknown public key variant: {byte}"
48 ))),
49 }
50 }
51
52 pub fn as_byte(&self) -> u8 {
54 *self as u8
55 }
56}
57
58#[derive(Clone, PartialEq, Eq)]
60pub struct AnyPublicKey {
61 pub variant: AnyPublicKeyVariant,
63 pub bytes: Vec<u8>,
65}
66
67impl AnyPublicKey {
68 pub fn new(variant: AnyPublicKeyVariant, bytes: Vec<u8>) -> Self {
70 Self { variant, bytes }
71 }
72
73 #[cfg(feature = "ed25519")]
75 pub fn ed25519(public_key: &crate::crypto::Ed25519PublicKey) -> Self {
76 Self {
77 variant: AnyPublicKeyVariant::Ed25519,
78 bytes: public_key.to_bytes().to_vec(),
79 }
80 }
81
82 #[cfg(feature = "secp256k1")]
85 pub fn secp256k1(public_key: &crate::crypto::Secp256k1PublicKey) -> Self {
86 Self {
87 variant: AnyPublicKeyVariant::Secp256k1,
88 bytes: public_key.to_uncompressed_bytes(),
89 }
90 }
91
92 #[cfg(feature = "secp256r1")]
95 pub fn secp256r1(public_key: &crate::crypto::Secp256r1PublicKey) -> Self {
96 Self {
97 variant: AnyPublicKeyVariant::Secp256r1,
98 bytes: public_key.to_uncompressed_bytes(),
99 }
100 }
101
102 pub fn to_bcs_bytes(&self) -> Vec<u8> {
107 let mut result = Vec::with_capacity(1 + 1 + self.bytes.len());
108 result.push(self.variant.as_byte());
109 result.extend(uleb128_encode(self.bytes.len()));
111 result.extend_from_slice(&self.bytes);
112 result
113 }
114
115 #[allow(unused_variables)]
126 pub fn verify(&self, message: &[u8], signature: &AnySignature) -> AptosResult<()> {
127 if signature.variant != self.variant {
128 return Err(AptosError::InvalidSignature(format!(
129 "signature variant {:?} doesn't match public key variant {:?}",
130 signature.variant, self.variant
131 )));
132 }
133
134 match self.variant {
135 #[cfg(feature = "ed25519")]
136 AnyPublicKeyVariant::Ed25519 => {
137 let pk = crate::crypto::Ed25519PublicKey::from_bytes(&self.bytes)?;
138 let sig = crate::crypto::Ed25519Signature::from_bytes(&signature.bytes)?;
139 pk.verify(message, &sig)
140 }
141 #[cfg(feature = "secp256k1")]
142 AnyPublicKeyVariant::Secp256k1 => {
143 let pk = crate::crypto::Secp256k1PublicKey::from_bytes(&self.bytes)?;
145 let sig = crate::crypto::Secp256k1Signature::from_bytes(&signature.bytes)?;
146 pk.verify(message, &sig)
147 }
148 #[cfg(feature = "secp256r1")]
149 AnyPublicKeyVariant::Secp256r1 => {
150 let pk = crate::crypto::Secp256r1PublicKey::from_bytes(&self.bytes)?;
152 let sig = crate::crypto::Secp256r1Signature::from_bytes(&signature.bytes)?;
153 pk.verify(message, &sig)
154 }
155 #[allow(unreachable_patterns)]
156 _ => Err(AptosError::InvalidPublicKey(format!(
157 "verification not supported for variant {:?}",
158 self.variant
159 ))),
160 }
161 }
162}
163
164impl fmt::Debug for AnyPublicKey {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 write!(
167 f,
168 "AnyPublicKey({:?}, {})",
169 self.variant,
170 const_hex::encode_prefixed(&self.bytes)
171 )
172 }
173}
174
175impl fmt::Display for AnyPublicKey {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 write!(
178 f,
179 "{:?}:{}",
180 self.variant,
181 const_hex::encode_prefixed(&self.bytes)
182 )
183 }
184}
185
186#[derive(Clone, PartialEq, Eq)]
188pub struct AnySignature {
189 pub variant: AnyPublicKeyVariant,
191 pub bytes: Vec<u8>,
193}
194
195impl AnySignature {
196 pub fn new(variant: AnyPublicKeyVariant, bytes: Vec<u8>) -> Self {
198 Self { variant, bytes }
199 }
200
201 #[cfg(feature = "ed25519")]
203 pub fn ed25519(signature: &crate::crypto::Ed25519Signature) -> Self {
204 Self {
205 variant: AnyPublicKeyVariant::Ed25519,
206 bytes: signature.to_bytes().to_vec(),
207 }
208 }
209
210 #[cfg(feature = "secp256k1")]
212 pub fn secp256k1(signature: &crate::crypto::Secp256k1Signature) -> Self {
213 Self {
214 variant: AnyPublicKeyVariant::Secp256k1,
215 bytes: signature.to_bytes().to_vec(),
216 }
217 }
218
219 #[cfg(feature = "secp256r1")]
221 pub fn secp256r1(signature: &crate::crypto::Secp256r1Signature) -> Self {
222 Self {
223 variant: AnyPublicKeyVariant::Secp256r1,
224 bytes: signature.to_bytes().to_vec(),
225 }
226 }
227
228 pub fn to_bcs_bytes(&self) -> Vec<u8> {
230 let mut result = Vec::with_capacity(1 + 1 + self.bytes.len());
231 result.push(self.variant.as_byte());
232 result.extend(uleb128_encode(self.bytes.len()));
234 result.extend_from_slice(&self.bytes);
235 result
236 }
237}
238
239#[allow(clippy::cast_possible_truncation)] #[inline]
244fn uleb128_encode(mut value: usize) -> Vec<u8> {
245 let mut result = Vec::with_capacity(if value < 128 { 1 } else { 2 });
247 loop {
248 let byte = (value & 0x7F) as u8;
249 value >>= 7;
250 if value == 0 {
251 result.push(byte);
252 break;
253 }
254 result.push(byte | 0x80);
255 }
256 result
257}
258
259fn uleb128_decode(bytes: &[u8]) -> Option<(usize, usize)> {
261 let mut result: usize = 0;
262 let mut shift = 0;
263 for (i, &byte) in bytes.iter().enumerate() {
264 result |= ((byte & 0x7F) as usize) << shift;
265 if byte & 0x80 == 0 {
266 return Some((result, i + 1));
267 }
268 shift += 7;
269 if shift >= 64 {
270 return None; }
272 }
273 None
274}
275
276impl fmt::Debug for AnySignature {
277 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278 write!(
279 f,
280 "AnySignature({:?}, {} bytes)",
281 self.variant,
282 self.bytes.len()
283 )
284 }
285}
286
287#[derive(Clone, PartialEq, Eq)]
291pub struct MultiKeyPublicKey {
292 public_keys: Vec<AnyPublicKey>,
294 threshold: u8,
296}
297
298impl MultiKeyPublicKey {
299 pub fn new(public_keys: Vec<AnyPublicKey>, threshold: u8) -> AptosResult<Self> {
314 if public_keys.is_empty() {
315 return Err(AptosError::InvalidPublicKey(
316 "multi-key requires at least one public key".into(),
317 ));
318 }
319 if public_keys.len() > MAX_NUM_OF_KEYS {
320 return Err(AptosError::InvalidPublicKey(format!(
321 "multi-key supports at most {} keys, got {}",
322 MAX_NUM_OF_KEYS,
323 public_keys.len()
324 )));
325 }
326 if threshold < MIN_THRESHOLD {
327 return Err(AptosError::InvalidPublicKey(
328 "threshold must be at least 1".into(),
329 ));
330 }
331 if threshold as usize > public_keys.len() {
332 return Err(AptosError::InvalidPublicKey(format!(
333 "threshold {} exceeds number of keys {}",
334 threshold,
335 public_keys.len()
336 )));
337 }
338 Ok(Self {
339 public_keys,
340 threshold,
341 })
342 }
343
344 pub fn num_keys(&self) -> usize {
346 self.public_keys.len()
347 }
348
349 pub fn threshold(&self) -> u8 {
351 self.threshold
352 }
353
354 pub fn public_keys(&self) -> &[AnyPublicKey] {
356 &self.public_keys
357 }
358
359 pub fn get(&self, index: usize) -> Option<&AnyPublicKey> {
361 self.public_keys.get(index)
362 }
363
364 #[allow(clippy::cast_possible_truncation)] pub fn to_bytes(&self) -> Vec<u8> {
369 let estimated_size = 2 + self.public_keys.len() * 36;
371 let mut bytes = Vec::with_capacity(estimated_size);
372
373 bytes.push(self.public_keys.len() as u8);
375
376 for pk in &self.public_keys {
378 bytes.extend(pk.to_bcs_bytes());
379 }
380
381 bytes.push(self.threshold);
383
384 bytes
385 }
386
387 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
399 const MAX_KEY_SIZE: usize = 128;
402
403 if bytes.is_empty() {
404 return Err(AptosError::InvalidPublicKey("empty bytes".into()));
405 }
406
407 let num_keys = bytes[0] as usize;
408 if num_keys == 0 || num_keys > MAX_NUM_OF_KEYS {
409 return Err(AptosError::InvalidPublicKey(format!(
410 "invalid number of keys: {num_keys}"
411 )));
412 }
413
414 let mut offset = 1;
415 let mut public_keys = Vec::with_capacity(num_keys);
416
417 for _ in 0..num_keys {
418 if offset >= bytes.len() {
419 return Err(AptosError::InvalidPublicKey("bytes too short".into()));
420 }
421
422 let variant = AnyPublicKeyVariant::from_byte(bytes[offset])?;
423 offset += 1;
424
425 let (len, len_bytes) = uleb128_decode(&bytes[offset..]).ok_or_else(|| {
427 AptosError::InvalidPublicKey("invalid ULEB128 length encoding".into())
428 })?;
429 offset += len_bytes;
430
431 if len > MAX_KEY_SIZE {
432 return Err(AptosError::InvalidPublicKey(format!(
433 "key size {len} exceeds maximum {MAX_KEY_SIZE}"
434 )));
435 }
436
437 if offset + len > bytes.len() {
438 return Err(AptosError::InvalidPublicKey(
439 "bytes too short for key".into(),
440 ));
441 }
442
443 let key_bytes = bytes[offset..offset + len].to_vec();
444 offset += len;
445
446 public_keys.push(AnyPublicKey::new(variant, key_bytes));
447 }
448
449 if offset >= bytes.len() {
450 return Err(AptosError::InvalidPublicKey(
451 "bytes too short for threshold".into(),
452 ));
453 }
454
455 let threshold = bytes[offset];
456
457 Self::new(public_keys, threshold)
458 }
459
460 pub fn to_address(&self) -> crate::types::AccountAddress {
462 crate::crypto::derive_address(&self.to_bytes(), crate::crypto::MULTI_KEY_SCHEME)
463 }
464
465 pub fn to_authentication_key(&self) -> [u8; 32] {
467 crate::crypto::derive_authentication_key(&self.to_bytes(), crate::crypto::MULTI_KEY_SCHEME)
468 }
469
470 pub fn verify(&self, message: &[u8], signature: &MultiKeySignature) -> AptosResult<()> {
479 if signature.num_signatures() < self.threshold as usize {
481 return Err(AptosError::SignatureVerificationFailed);
482 }
483
484 for (index, sig) in signature.signatures() {
486 if *index as usize >= self.public_keys.len() {
487 return Err(AptosError::InvalidSignature(format!(
488 "signer index {} out of bounds (max {})",
489 index,
490 self.public_keys.len() - 1
491 )));
492 }
493 let pk = &self.public_keys[*index as usize];
494 pk.verify(message, sig)?;
495 }
496
497 Ok(())
498 }
499}
500
501impl fmt::Debug for MultiKeyPublicKey {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 write!(
504 f,
505 "MultiKeyPublicKey({}-of-{} keys)",
506 self.threshold,
507 self.public_keys.len()
508 )
509 }
510}
511
512impl fmt::Display for MultiKeyPublicKey {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
515 }
516}
517
518#[derive(Clone, PartialEq, Eq)]
520pub struct MultiKeySignature {
521 signatures: Vec<(u8, AnySignature)>,
523 bitmap: [u8; 4],
525}
526
527impl MultiKeySignature {
528 pub fn new(mut signatures: Vec<(u8, AnySignature)>) -> AptosResult<Self> {
542 if signatures.is_empty() {
543 return Err(AptosError::InvalidSignature(
544 "multi-key signature requires at least one signature".into(),
545 ));
546 }
547 if signatures.len() > MAX_NUM_OF_KEYS {
548 return Err(AptosError::InvalidSignature(format!(
549 "too many signatures: {} (max {})",
550 signatures.len(),
551 MAX_NUM_OF_KEYS
552 )));
553 }
554
555 signatures.sort_by_key(|(idx, _)| *idx);
557
558 let mut bitmap = [0u8; 4];
560 let mut last_index: Option<u8> = None;
561
562 for (index, _) in &signatures {
563 if *index as usize >= MAX_NUM_OF_KEYS {
564 return Err(AptosError::InvalidSignature(format!(
565 "signer index {} out of bounds (max {})",
566 index,
567 MAX_NUM_OF_KEYS - 1
568 )));
569 }
570 if last_index == Some(*index) {
571 return Err(AptosError::InvalidSignature(format!(
572 "duplicate signer index {index}"
573 )));
574 }
575 last_index = Some(*index);
576
577 let byte_index = (index / 8) as usize;
579 let bit_index = index % 8;
580 bitmap[byte_index] |= 1 << bit_index;
581 }
582
583 Ok(Self { signatures, bitmap })
584 }
585
586 pub fn num_signatures(&self) -> usize {
588 self.signatures.len()
589 }
590
591 pub fn signatures(&self) -> &[(u8, AnySignature)] {
593 &self.signatures
594 }
595
596 pub fn bitmap(&self) -> &[u8; 4] {
598 &self.bitmap
599 }
600
601 pub fn has_signature(&self, index: u8) -> bool {
603 if index as usize >= MAX_NUM_OF_KEYS {
604 return false;
605 }
606 let byte_index = (index / 8) as usize;
607 let bit_index = index % 8;
608 (self.bitmap[byte_index] >> bit_index) & 1 == 1
609 }
610
611 #[allow(clippy::cast_possible_truncation)] pub fn to_bytes(&self) -> Vec<u8> {
616 let estimated_size = 5 + self.signatures.len() * 68;
618 let mut bytes = Vec::with_capacity(estimated_size);
619
620 bytes.push(self.signatures.len() as u8);
622
623 for (_, sig) in &self.signatures {
625 bytes.extend(sig.to_bcs_bytes());
626 }
627
628 bytes.extend_from_slice(&self.bitmap);
630
631 bytes
632 }
633
634 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
646 const MAX_SIGNATURE_SIZE: usize = 128;
649
650 if bytes.len() < 5 {
651 return Err(AptosError::InvalidSignature("bytes too short".into()));
652 }
653
654 let num_sigs = bytes[0] as usize;
655 if num_sigs == 0 || num_sigs > MAX_NUM_OF_KEYS {
656 return Err(AptosError::InvalidSignature(format!(
657 "invalid number of signatures: {num_sigs}"
658 )));
659 }
660
661 let bitmap_start = bytes.len() - 4;
663 let mut bitmap = [0u8; 4];
664 bitmap.copy_from_slice(&bytes[bitmap_start..]);
665
666 let mut offset = 1;
668 let mut signatures = Vec::with_capacity(num_sigs);
669
670 let mut signer_indices = Vec::new();
672 #[allow(clippy::cast_possible_truncation)]
673 for bit_pos in 0..(MAX_NUM_OF_KEYS as u8) {
674 let byte_idx = (bit_pos / 8) as usize;
675 let bit_idx = bit_pos % 8;
676 if (bitmap[byte_idx] >> bit_idx) & 1 == 1 {
677 signer_indices.push(bit_pos);
678 }
679 }
680
681 if signer_indices.len() != num_sigs {
682 return Err(AptosError::InvalidSignature(
683 "bitmap doesn't match number of signatures".into(),
684 ));
685 }
686
687 for &index in &signer_indices {
688 if offset >= bitmap_start {
689 return Err(AptosError::InvalidSignature("bytes too short".into()));
690 }
691
692 let variant = AnyPublicKeyVariant::from_byte(bytes[offset])?;
693 offset += 1;
694
695 let (len, len_bytes) =
697 uleb128_decode(&bytes[offset..bitmap_start]).ok_or_else(|| {
698 AptosError::InvalidSignature("invalid ULEB128 length encoding".into())
699 })?;
700 offset += len_bytes;
701
702 if len > MAX_SIGNATURE_SIZE {
703 return Err(AptosError::InvalidSignature(format!(
704 "signature size {len} exceeds maximum {MAX_SIGNATURE_SIZE}"
705 )));
706 }
707
708 if offset + len > bitmap_start {
709 return Err(AptosError::InvalidSignature(
710 "bytes too short for signature".into(),
711 ));
712 }
713
714 let sig_bytes = bytes[offset..offset + len].to_vec();
715 offset += len;
716
717 signatures.push((index, AnySignature::new(variant, sig_bytes)));
718 }
719
720 Ok(Self { signatures, bitmap })
721 }
722}
723
724impl fmt::Debug for MultiKeySignature {
725 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
726 write!(
727 f,
728 "MultiKeySignature({} signatures, bitmap={:?})",
729 self.signatures.len(),
730 self.bitmap
731 )
732 }
733}
734
735impl fmt::Display for MultiKeySignature {
736 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
737 f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
738 }
739}
740
741#[cfg(test)]
742mod tests {
743 use super::*;
744
745 #[test]
746 fn test_any_public_key_variant_from_byte() {
747 assert_eq!(
748 AnyPublicKeyVariant::from_byte(0).unwrap(),
749 AnyPublicKeyVariant::Ed25519
750 );
751 assert_eq!(
752 AnyPublicKeyVariant::from_byte(1).unwrap(),
753 AnyPublicKeyVariant::Secp256k1
754 );
755 assert_eq!(
756 AnyPublicKeyVariant::from_byte(2).unwrap(),
757 AnyPublicKeyVariant::Secp256r1
758 );
759 assert_eq!(
760 AnyPublicKeyVariant::from_byte(3).unwrap(),
761 AnyPublicKeyVariant::Keyless
762 );
763 assert!(AnyPublicKeyVariant::from_byte(4).is_err());
764 assert!(AnyPublicKeyVariant::from_byte(255).is_err());
765 }
766
767 #[test]
768 fn test_any_public_key_variant_as_byte() {
769 assert_eq!(AnyPublicKeyVariant::Ed25519.as_byte(), 0);
770 assert_eq!(AnyPublicKeyVariant::Secp256k1.as_byte(), 1);
771 assert_eq!(AnyPublicKeyVariant::Secp256r1.as_byte(), 2);
772 assert_eq!(AnyPublicKeyVariant::Keyless.as_byte(), 3);
773 }
774
775 #[test]
776 fn test_any_public_key_new() {
777 let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0x11; 32]);
778 assert_eq!(pk.variant, AnyPublicKeyVariant::Ed25519);
779 assert_eq!(pk.bytes.len(), 32);
780 assert_eq!(pk.bytes[0], 0x11);
781 }
782
783 #[test]
784 fn test_any_public_key_to_bcs_bytes() {
785 let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0xaa; 32]);
786 let bcs = pk.to_bcs_bytes();
787
788 assert_eq!(bcs[0], 0); assert_eq!(bcs[1], 32); assert_eq!(bcs[2], 0xaa); assert_eq!(bcs.len(), 1 + 1 + 32); }
794
795 #[test]
796 fn test_any_public_key_debug() {
797 let pk = AnyPublicKey::new(AnyPublicKeyVariant::Secp256k1, vec![0xbb; 33]);
798 let debug = format!("{pk:?}");
799 assert!(debug.contains("Secp256k1"));
800 assert!(debug.contains("0x"));
801 }
802
803 #[test]
804 fn test_any_signature_new() {
805 let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xcc; 64]);
806 assert_eq!(sig.variant, AnyPublicKeyVariant::Ed25519);
807 assert_eq!(sig.bytes.len(), 64);
808 }
809
810 #[test]
811 fn test_any_signature_to_bcs_bytes() {
812 let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xdd; 64]);
813 let bcs = sig.to_bcs_bytes();
814
815 assert_eq!(bcs[0], 0); assert_eq!(bcs[1], 64); assert_eq!(bcs[2], 0xdd); assert_eq!(bcs.len(), 1 + 1 + 64); }
821
822 #[test]
823 fn test_any_signature_debug() {
824 let sig = AnySignature::new(AnyPublicKeyVariant::Secp256r1, vec![0xee; 64]);
825 let debug = format!("{sig:?}");
826 assert!(debug.contains("Secp256r1"));
827 assert!(debug.contains("64 bytes"));
828 }
829
830 #[test]
831 fn test_any_public_key_verify_mismatched_variant() {
832 let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0; 32]);
833 let sig = AnySignature::new(AnyPublicKeyVariant::Secp256k1, vec![0; 64]);
834
835 let result = pk.verify(b"message", &sig);
836 assert!(result.is_err());
837 assert!(result.unwrap_err().to_string().contains("variant"));
838 }
839
840 #[test]
841 fn test_multi_key_signature_insufficient_sigs() {
842 let result = MultiKeySignature::new(vec![]);
844 assert!(result.is_err());
845 }
846
847 #[test]
848 fn test_multi_key_signature_duplicate_indices() {
849 let sig1 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
850 let sig2 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![1; 64]);
851
852 let result = MultiKeySignature::new(vec![(0, sig1.clone()), (0, sig2)]);
854 assert!(result.is_err());
855 }
856
857 #[test]
858 fn test_multi_key_signature_index_out_of_range() {
859 let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
860
861 let result = MultiKeySignature::new(vec![(32, sig)]);
863 assert!(result.is_err());
864 }
865
866 #[test]
867 fn test_multi_key_signature_basic() {
868 let sig1 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xaa; 64]);
869 let sig2 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xbb; 64]);
870
871 let multi_sig = MultiKeySignature::new(vec![(0, sig1), (5, sig2)]).unwrap();
872
873 assert_eq!(multi_sig.num_signatures(), 2);
874 assert!(multi_sig.has_signature(0));
875 assert!(!multi_sig.has_signature(1));
876 assert!(multi_sig.has_signature(5));
877 }
878
879 #[test]
880 fn test_multi_key_signature_debug_display() {
881 let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
882 let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
883
884 let debug = format!("{multi_sig:?}");
885 let display = format!("{multi_sig}");
886
887 assert!(debug.contains("MultiKeySignature"));
888 assert!(display.starts_with("0x"));
889 }
890
891 #[test]
892 #[cfg(feature = "ed25519")]
893 fn test_multi_key_public_key_creation() {
894 use crate::crypto::Ed25519PrivateKey;
895
896 let keys: Vec<_> = (0..3)
897 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
898 .collect();
899
900 let multi_pk = MultiKeyPublicKey::new(keys.clone(), 2).unwrap();
902 assert_eq!(multi_pk.num_keys(), 3);
903 assert_eq!(multi_pk.threshold(), 2);
904
905 assert!(MultiKeyPublicKey::new(keys.clone(), 4).is_err());
907
908 assert!(MultiKeyPublicKey::new(keys.clone(), 0).is_err());
910
911 assert!(MultiKeyPublicKey::new(vec![], 1).is_err());
913 }
914
915 #[test]
916 #[cfg(all(feature = "ed25519", feature = "secp256k1"))]
917 fn test_multi_key_mixed_types() {
918 use crate::crypto::{Ed25519PrivateKey, Secp256k1PrivateKey};
919
920 let ed_key = AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key());
922 let secp_key = AnyPublicKey::secp256k1(&Secp256k1PrivateKey::generate().public_key());
923
924 let multi_pk = MultiKeyPublicKey::new(vec![ed_key, secp_key], 2).unwrap();
925 assert_eq!(multi_pk.num_keys(), 2);
926 assert_eq!(
927 multi_pk.get(0).unwrap().variant,
928 AnyPublicKeyVariant::Ed25519
929 );
930 assert_eq!(
931 multi_pk.get(1).unwrap().variant,
932 AnyPublicKeyVariant::Secp256k1
933 );
934 }
935
936 #[test]
937 #[cfg(feature = "ed25519")]
938 fn test_multi_key_sign_verify() {
939 use crate::crypto::Ed25519PrivateKey;
940
941 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
942 let public_keys: Vec<_> = private_keys
943 .iter()
944 .map(|k| AnyPublicKey::ed25519(&k.public_key()))
945 .collect();
946
947 let multi_pk = MultiKeyPublicKey::new(public_keys, 2).unwrap();
948 let message = b"test message";
949
950 let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
952 let sig2 = AnySignature::ed25519(&private_keys[2].sign(message));
953
954 let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
955
956 assert!(multi_pk.verify(message, &multi_sig).is_ok());
958
959 assert!(multi_pk.verify(b"wrong message", &multi_sig).is_err());
961 }
962
963 #[test]
964 #[cfg(feature = "ed25519")]
965 fn test_multi_key_bytes_roundtrip() {
966 use crate::crypto::Ed25519PrivateKey;
967
968 let keys: Vec<_> = (0..3)
969 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
970 .collect();
971 let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
972
973 let bytes = multi_pk.to_bytes();
974 let restored = MultiKeyPublicKey::from_bytes(&bytes).unwrap();
975
976 assert_eq!(multi_pk.threshold(), restored.threshold());
977 assert_eq!(multi_pk.num_keys(), restored.num_keys());
978 }
979
980 #[test]
981 #[cfg(feature = "ed25519")]
982 fn test_multi_key_signature_bytes_roundtrip() {
983 use crate::crypto::Ed25519PrivateKey;
984
985 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
986 let message = b"test";
987
988 let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
989 let sig2 = AnySignature::ed25519(&private_keys[2].sign(message));
990
991 let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
992
993 let bytes = multi_sig.to_bytes();
994 let restored = MultiKeySignature::from_bytes(&bytes).unwrap();
995
996 assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
997 assert_eq!(multi_sig.bitmap(), restored.bitmap());
998 }
999
1000 #[test]
1001 #[cfg(feature = "ed25519")]
1002 fn test_signature_bitmap() {
1003 use crate::crypto::Ed25519PrivateKey;
1004
1005 let private_keys: Vec<_> = (0..5).map(|_| Ed25519PrivateKey::generate()).collect();
1006 let message = b"test";
1007
1008 let signatures: Vec<_> = [1, 3, 4]
1010 .iter()
1011 .map(|&i| {
1012 (
1013 i,
1014 AnySignature::ed25519(&private_keys[i as usize].sign(message)),
1015 )
1016 })
1017 .collect();
1018
1019 let multi_sig = MultiKeySignature::new(signatures).unwrap();
1020
1021 assert!(!multi_sig.has_signature(0));
1022 assert!(multi_sig.has_signature(1));
1023 assert!(!multi_sig.has_signature(2));
1024 assert!(multi_sig.has_signature(3));
1025 assert!(multi_sig.has_signature(4));
1026 assert!(!multi_sig.has_signature(5));
1027 }
1028
1029 #[test]
1030 fn test_multi_key_public_key_empty_keys() {
1031 let result = MultiKeyPublicKey::new(vec![], 1);
1032 assert!(result.is_err());
1033 assert!(result.unwrap_err().to_string().contains("at least one"));
1034 }
1035
1036 #[test]
1037 #[cfg(feature = "ed25519")]
1038 fn test_multi_key_public_key_threshold_zero() {
1039 use crate::crypto::Ed25519PrivateKey;
1040
1041 let keys: Vec<_> = (0..2)
1042 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1043 .collect();
1044 let result = MultiKeyPublicKey::new(keys, 0);
1045 assert!(result.is_err());
1046 assert!(result.unwrap_err().to_string().contains("at least 1"));
1047 }
1048
1049 #[test]
1050 #[cfg(feature = "ed25519")]
1051 fn test_multi_key_public_key_threshold_exceeds() {
1052 use crate::crypto::Ed25519PrivateKey;
1053
1054 let keys: Vec<_> = (0..2)
1055 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1056 .collect();
1057 let result = MultiKeyPublicKey::new(keys, 5);
1058 assert!(result.is_err());
1059 assert!(result.unwrap_err().to_string().contains("exceed"));
1060 }
1061
1062 #[test]
1063 #[cfg(feature = "ed25519")]
1064 fn test_multi_key_signature_empty() {
1065 let result = MultiKeySignature::new(vec![]);
1066 assert!(result.is_err());
1067 assert!(result.unwrap_err().to_string().contains("at least one"));
1068 }
1069
1070 #[test]
1071 #[cfg(feature = "ed25519")]
1072 fn test_multi_key_signature_duplicate_index() {
1073 use crate::crypto::Ed25519PrivateKey;
1074
1075 let private_key = Ed25519PrivateKey::generate();
1076 let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1077
1078 let result = MultiKeySignature::new(vec![(0, sig.clone()), (0, sig)]);
1079 assert!(result.is_err());
1080 assert!(result.unwrap_err().to_string().contains("duplicate"));
1081 }
1082
1083 #[test]
1084 #[cfg(feature = "ed25519")]
1085 fn test_multi_key_public_key_accessors() {
1086 use crate::crypto::Ed25519PrivateKey;
1087
1088 let keys: Vec<_> = (0..3)
1089 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1090 .collect();
1091 let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1092
1093 assert_eq!(multi_pk.threshold(), 2);
1094 assert_eq!(multi_pk.num_keys(), 3);
1095 assert_eq!(multi_pk.public_keys().len(), 3);
1096 }
1097
1098 #[test]
1099 #[cfg(feature = "ed25519")]
1100 fn test_multi_key_signature_accessors() {
1101 use crate::crypto::Ed25519PrivateKey;
1102
1103 let private_key = Ed25519PrivateKey::generate();
1104 let sig0 = AnySignature::ed25519(&private_key.sign(b"test"));
1105 let sig2 = AnySignature::ed25519(&private_key.sign(b"test"));
1106
1107 let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
1108
1109 assert_eq!(multi_sig.num_signatures(), 2);
1110 assert_eq!(multi_sig.signatures().len(), 2);
1111 }
1112
1113 #[test]
1114 #[cfg(feature = "ed25519")]
1115 fn test_multi_key_public_key_debug() {
1116 use crate::crypto::Ed25519PrivateKey;
1117
1118 let keys: Vec<_> = (0..2)
1119 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1120 .collect();
1121 let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1122
1123 let debug = format!("{multi_pk:?}");
1124 assert!(debug.contains("MultiKeyPublicKey"));
1125 }
1126
1127 #[test]
1128 #[cfg(feature = "ed25519")]
1129 fn test_multi_key_signature_debug() {
1130 use crate::crypto::Ed25519PrivateKey;
1131
1132 let private_key = Ed25519PrivateKey::generate();
1133 let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1134 let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
1135
1136 let debug = format!("{multi_sig:?}");
1137 assert!(debug.contains("MultiKeySignature"));
1138 }
1139
1140 #[test]
1141 #[cfg(feature = "ed25519")]
1142 fn test_multi_key_public_key_display() {
1143 use crate::crypto::Ed25519PrivateKey;
1144
1145 let keys: Vec<_> = (0..2)
1146 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1147 .collect();
1148 let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1149
1150 let display = format!("{multi_pk}");
1151 assert!(display.starts_with("0x"));
1152 }
1153
1154 #[test]
1155 #[cfg(feature = "ed25519")]
1156 fn test_multi_key_signature_display() {
1157 use crate::crypto::Ed25519PrivateKey;
1158
1159 let private_key = Ed25519PrivateKey::generate();
1160 let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1161 let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
1162
1163 let display = format!("{multi_sig}");
1164 assert!(display.starts_with("0x"));
1165 }
1166
1167 #[test]
1168 #[cfg(feature = "ed25519")]
1169 fn test_multi_key_public_key_to_address() {
1170 use crate::crypto::Ed25519PrivateKey;
1171
1172 let keys: Vec<_> = (0..2)
1173 .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1174 .collect();
1175 let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1176
1177 let address = multi_pk.to_address();
1178 assert!(!address.is_zero());
1179 }
1180
1181 #[test]
1182 fn test_any_public_key_variant_debug() {
1183 let variant = AnyPublicKeyVariant::Ed25519;
1184 let debug = format!("{variant:?}");
1185 assert!(debug.contains("Ed25519"));
1186 }
1187
1188 #[test]
1189 #[cfg(feature = "ed25519")]
1190 fn test_any_public_key_ed25519_debug() {
1191 use crate::crypto::Ed25519PrivateKey;
1192
1193 let pk = AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key());
1194 let debug = format!("{pk:?}");
1195 assert!(debug.contains("Ed25519"));
1196 }
1197
1198 #[test]
1199 #[cfg(feature = "ed25519")]
1200 fn test_any_signature_ed25519_debug() {
1201 use crate::crypto::Ed25519PrivateKey;
1202
1203 let private_key = Ed25519PrivateKey::generate();
1204 let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1205 let debug = format!("{sig:?}");
1206 assert!(debug.contains("Ed25519"));
1207 }
1208
1209 #[test]
1210 #[cfg(feature = "ed25519")]
1211 fn test_multi_key_insufficient_signatures() {
1212 use crate::crypto::Ed25519PrivateKey;
1213
1214 let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
1215 let public_keys: Vec<_> = private_keys
1216 .iter()
1217 .map(|k| AnyPublicKey::ed25519(&k.public_key()))
1218 .collect();
1219
1220 let multi_pk = MultiKeyPublicKey::new(public_keys, 2).unwrap();
1221 let message = b"test message";
1222
1223 let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
1225 let multi_sig = MultiKeySignature::new(vec![(0, sig0)]).unwrap();
1226
1227 let result = multi_pk.verify(message, &multi_sig);
1229 assert!(result.is_err());
1230 }
1231}