Skip to main content

aptos_sdk/crypto/
multi_ed25519.rs

1//! Multi-Ed25519 signature scheme implementation.
2//!
3//! Multi-Ed25519 enables M-of-N threshold signatures where M signatures
4//! out of N public keys are required to authorize a transaction.
5
6use 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
14/// Maximum number of keys in a multi-Ed25519 account.
15pub const MAX_NUM_OF_KEYS: usize = 32;
16
17// Compile-time assertion: MAX_NUM_OF_KEYS must fit in u8 for bitmap operations
18const _: () = assert!(MAX_NUM_OF_KEYS <= u8::MAX as usize);
19
20/// Minimum threshold (at least 1 signature required).
21pub const MIN_THRESHOLD: u8 = 1;
22
23/// A multi-Ed25519 public key.
24///
25/// This is a collection of Ed25519 public keys with a threshold value.
26/// M-of-N signatures are required where M = threshold and N = number of keys.
27///
28/// # Example
29///
30/// ```rust,ignore
31/// use aptos_sdk::crypto::{Ed25519PrivateKey, MultiEd25519PublicKey};
32///
33/// let keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate().public_key()).collect();
34/// let multi_pk = MultiEd25519PublicKey::new(keys, 2).unwrap(); // 2-of-3
35/// ```
36#[derive(Clone, PartialEq, Eq)]
37pub struct MultiEd25519PublicKey {
38    /// The individual public keys.
39    public_keys: Vec<Ed25519PublicKey>,
40    /// The required threshold (M in M-of-N).
41    threshold: u8,
42}
43
44impl MultiEd25519PublicKey {
45    /// Creates a new multi-Ed25519 public key.
46    ///
47    /// # Arguments
48    ///
49    /// * `public_keys` - The individual Ed25519 public keys
50    /// * `threshold` - The number of signatures required (M in M-of-N)
51    ///
52    /// # Errors
53    ///
54    /// Returns an error if:
55    /// - No public keys are provided
56    /// - More than 32 public keys are provided
57    /// - Threshold is 0
58    /// - Threshold exceeds the number of keys
59    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    /// Returns the number of public keys.
91    pub fn num_keys(&self) -> usize {
92        self.public_keys.len()
93    }
94
95    /// Returns the threshold (M in M-of-N).
96    pub fn threshold(&self) -> u8 {
97        self.threshold
98    }
99
100    /// Returns the individual public keys.
101    pub fn public_keys(&self) -> &[Ed25519PublicKey] {
102        &self.public_keys
103    }
104
105    /// Serializes the public key to bytes.
106    ///
107    /// Format: `public_key_1` || `public_key_2` || ... || `public_key_n` || threshold
108    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    /// Creates a public key from bytes.
118    ///
119    /// # Errors
120    ///
121    /// Returns [`AptosError::InvalidPublicKey`] if:
122    /// - The bytes are empty
123    /// - The bytes are too short (less than 33 bytes for one key + threshold)
124    /// - The key bytes length is not a multiple of 32 bytes
125    /// - Any individual public key fails to parse
126    /// - The threshold is invalid (0, exceeds number of keys, etc.)
127    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    /// Derives the account address for this multi-Ed25519 public key.
163    pub fn to_address(&self) -> crate::types::AccountAddress {
164        crate::crypto::derive_address(&self.to_bytes(), crate::crypto::MULTI_ED25519_SCHEME)
165    }
166
167    /// Derives the authentication key for this public key.
168    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    /// Verifies a multi-Ed25519 signature against a message.
176    ///
177    /// # Errors
178    ///
179    /// This function will return an error if:
180    /// - The number of signatures is less than the threshold
181    /// - Any individual signature verification fails
182    /// - A signer index is out of bounds
183    pub fn verify(&self, message: &[u8], signature: &MultiEd25519Signature) -> AptosResult<()> {
184        // Check that we have enough signatures
185        if signature.num_signatures() < self.threshold as usize {
186            return Err(AptosError::SignatureVerificationFailed);
187        }
188
189        // Verify each signature
190        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; // Variable length
208
209    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/// A multi-Ed25519 signature.
274///
275/// This contains individual Ed25519 signatures along with a bitmap indicating
276/// which signers provided signatures.
277#[derive(Clone, PartialEq, Eq)]
278pub struct MultiEd25519Signature {
279    /// Individual signatures with their signer index.
280    signatures: Vec<(u8, Ed25519Signature)>,
281    /// Bitmap indicating which keys signed (little-endian).
282    bitmap: [u8; 4],
283}
284
285impl MultiEd25519Signature {
286    /// Creates a new multi-Ed25519 signature from individual signatures.
287    ///
288    /// # Arguments
289    ///
290    /// * `signatures` - Vec of (`signer_index`, signature) pairs
291    ///
292    /// The signer indices must be in ascending order and within bounds.
293    ///
294    /// # Errors
295    ///
296    /// Returns [`AptosError::InvalidSignature`] if:
297    /// - No signatures are provided
298    /// - More than 32 signatures are provided
299    /// - A signer index is out of bounds (>= 32)
300    /// - Duplicate signer indices are present
301    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        // Sort by index
316        signatures.sort_by_key(|(idx, _)| *idx);
317
318        // Check for duplicates and bounds
319        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            // Set bit in bitmap
338            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    /// Creates a signature from bytes.
347    ///
348    /// Format: `signature_1` || `signature_2` || ... || `signature_m` || bitmap (4 bytes)
349    ///
350    /// # Errors
351    ///
352    /// Returns [`AptosError::InvalidSignature`] if:
353    /// - The bytes are too short (less than 4 bytes for bitmap)
354    /// - The signature bytes length doesn't match the expected number of signatures from the bitmap
355    /// - Any individual signature fails to parse
356    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        // Count signatures from bitmap
368        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        // Parse signatures (MAX_NUM_OF_KEYS is 32, which fits in u8)
379        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    /// Serializes the signature to bytes.
400    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    /// Returns the number of signatures.
410    pub fn num_signatures(&self) -> usize {
411        self.signatures.len()
412    }
413
414    /// Returns the individual signatures with their indices.
415    pub fn signatures(&self) -> &[(u8, Ed25519Signature)] {
416        &self.signatures
417    }
418
419    /// Returns the signer bitmap.
420    pub fn bitmap(&self) -> &[u8; 4] {
421        &self.bitmap
422    }
423
424    /// Checks if a particular index signed.
425    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; // Variable length
438
439    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        // Valid 2-of-3
507        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        // Valid 3-of-3
512        let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 3).unwrap();
513        assert_eq!(multi_pk.threshold(), 3);
514
515        // Invalid: threshold > num_keys
516        assert!(MultiEd25519PublicKey::new(keys.clone(), 4).is_err());
517
518        // Invalid: threshold = 0
519        assert!(MultiEd25519PublicKey::new(keys.clone(), 0).is_err());
520
521        // Invalid: empty keys
522        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        // Sign with keys 0 and 2 (2-of-3)
537        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        // Verify should succeed
543        assert!(multi_pk.verify(message, &multi_sig).is_ok());
544
545        // Wrong message should fail
546        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        // Only 1 signature (need 2)
561        let sig0 = private_keys[0].sign(message);
562        let multi_sig = MultiEd25519Signature::new(vec![(0, sig0)]).unwrap();
563
564        // Should fail due to insufficient signatures
565        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        // Same keys should produce same address
611        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        // Sign with indices 1, 3, 4
621        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) // MAX_NUM_OF_KEYS is 32
639            .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        // Check bitmap has bits 0 and 2 set (little-endian 4 bytes)
668        let bitmap_bytes = multi_sig.bitmap();
669        // Bit 0 and bit 2 set means first byte should be 0b00000101 = 5
670        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        // Index 33 is out of bounds (MAX_NUM_OF_KEYS is 32)
685        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        // Duplicate index 0
696        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        // Too short - not even a threshold byte
703        let result = MultiEd25519PublicKey::from_bytes(&[]);
704        assert!(result.is_err());
705
706        // Just a threshold, no keys
707        let result = MultiEd25519PublicKey::from_bytes(&[2]);
708        assert!(result.is_err());
709
710        // Invalid length - not a multiple of 32 + 1
711        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        // Too short
718        let result = MultiEd25519Signature::from_bytes(&[]);
719        assert!(result.is_err());
720
721        // Just bitmap, no signatures
722        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        // Sign with indices 0 and 5 (5 is out of bounds for 3 keys)
738        let sig0 = private_keys[0].sign(message);
739        let sig5 = private_keys[0].sign(message); // Use same key, doesn't matter for this test
740
741        // Create bitmap with bit 5 set
742        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        // Verification should fail because index 5 is out of bounds
751        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        // Sign with key 0 but claim it's from key 1
767        let sig0 = private_keys[0].sign(message);
768        let sig1 = private_keys[0].sign(message); // Wrong key for index 1
769
770        let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
771
772        // Verification should fail because sig at index 1 doesn't match key 1
773        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]; // Less than 4 bytes (bitmap)
832        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        // Create bytes with bitmap indicating 1 signature but wrong number of bytes
840        let mut bytes = vec![0u8; 10]; // Not a multiple of signature length
841        // Set bitmap to indicate 1 signature (bit 0 set)
842        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)); // Out of bounds
861    }
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)]); // Index 32 is out of bounds
960        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        // Invalid length (not a multiple of ED25519_PUBLIC_KEY_LENGTH + 1 for threshold)
977        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}