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        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/// A multi-Ed25519 signature.
272///
273/// This contains individual Ed25519 signatures along with a bitmap indicating
274/// which signers provided signatures.
275#[derive(Clone, PartialEq, Eq)]
276pub struct MultiEd25519Signature {
277    /// Individual signatures with their signer index.
278    signatures: Vec<(u8, Ed25519Signature)>,
279    /// Bitmap indicating which keys signed (little-endian).
280    bitmap: [u8; 4],
281}
282
283impl MultiEd25519Signature {
284    /// Creates a new multi-Ed25519 signature from individual signatures.
285    ///
286    /// # Arguments
287    ///
288    /// * `signatures` - Vec of (`signer_index`, signature) pairs
289    ///
290    /// The signer indices must be in ascending order and within bounds.
291    ///
292    /// # Errors
293    ///
294    /// Returns [`AptosError::InvalidSignature`] if:
295    /// - No signatures are provided
296    /// - More than 32 signatures are provided
297    /// - A signer index is out of bounds (>= 32)
298    /// - Duplicate signer indices are present
299    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        // Sort by index
314        signatures.sort_by_key(|(idx, _)| *idx);
315
316        // Check for duplicates and bounds
317        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            // Set bit in bitmap
336            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    /// Creates a signature from bytes.
345    ///
346    /// Format: `signature_1` || `signature_2` || ... || `signature_m` || bitmap (4 bytes)
347    ///
348    /// # Errors
349    ///
350    /// Returns [`AptosError::InvalidSignature`] if:
351    /// - The bytes are too short (less than 4 bytes for bitmap)
352    /// - The signature bytes length doesn't match the expected number of signatures from the bitmap
353    /// - Any individual signature fails to parse
354    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        // Count signatures from bitmap
366        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        // Parse signatures (MAX_NUM_OF_KEYS is 32, which fits in u8)
377        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    /// Serializes the signature to bytes.
398    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    /// Returns the number of signatures.
408    pub fn num_signatures(&self) -> usize {
409        self.signatures.len()
410    }
411
412    /// Returns the individual signatures with their indices.
413    pub fn signatures(&self) -> &[(u8, Ed25519Signature)] {
414        &self.signatures
415    }
416
417    /// Returns the signer bitmap.
418    pub fn bitmap(&self) -> &[u8; 4] {
419        &self.bitmap
420    }
421
422    /// Checks if a particular index signed.
423    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; // Variable length
436
437    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        // Valid 2-of-3
503        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        // Valid 3-of-3
508        let multi_pk = MultiEd25519PublicKey::new(keys.clone(), 3).unwrap();
509        assert_eq!(multi_pk.threshold(), 3);
510
511        // Invalid: threshold > num_keys
512        assert!(MultiEd25519PublicKey::new(keys.clone(), 4).is_err());
513
514        // Invalid: threshold = 0
515        assert!(MultiEd25519PublicKey::new(keys.clone(), 0).is_err());
516
517        // Invalid: empty keys
518        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        // Sign with keys 0 and 2 (2-of-3)
533        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        // Verify should succeed
539        assert!(multi_pk.verify(message, &multi_sig).is_ok());
540
541        // Wrong message should fail
542        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        // Only 1 signature (need 2)
557        let sig0 = private_keys[0].sign(message);
558        let multi_sig = MultiEd25519Signature::new(vec![(0, sig0)]).unwrap();
559
560        // Should fail due to insufficient signatures
561        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        // Same keys should produce same address
607        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        // Sign with indices 1, 3, 4
617        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) // MAX_NUM_OF_KEYS is 32
635            .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        // Check bitmap has bits 0 and 2 set (little-endian 4 bytes)
664        let bitmap_bytes = multi_sig.bitmap();
665        // Bit 0 and bit 2 set means first byte should be 0b00000101 = 5
666        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        // Index 33 is out of bounds (MAX_NUM_OF_KEYS is 32)
681        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        // Duplicate index 0
692        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        // Too short - not even a threshold byte
699        let result = MultiEd25519PublicKey::from_bytes(&[]);
700        assert!(result.is_err());
701
702        // Just a threshold, no keys
703        let result = MultiEd25519PublicKey::from_bytes(&[2]);
704        assert!(result.is_err());
705
706        // Invalid length - not a multiple of 32 + 1
707        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        // Too short
714        let result = MultiEd25519Signature::from_bytes(&[]);
715        assert!(result.is_err());
716
717        // Just bitmap, no signatures
718        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        // Sign with indices 0 and 5 (5 is out of bounds for 3 keys)
734        let sig0 = private_keys[0].sign(message);
735        let sig5 = private_keys[0].sign(message); // Use same key, doesn't matter for this test
736
737        // Create bitmap with bit 5 set
738        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        // Verification should fail because index 5 is out of bounds
747        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        // Sign with key 0 but claim it's from key 1
763        let sig0 = private_keys[0].sign(message);
764        let sig1 = private_keys[0].sign(message); // Wrong key for index 1
765
766        let multi_sig = MultiEd25519Signature::new(vec![(0, sig0), (1, sig1)]).unwrap();
767
768        // Verification should fail because sig at index 1 doesn't match key 1
769        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]; // Less than 4 bytes (bitmap)
828        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        // Create bytes with bitmap indicating 1 signature but wrong number of bytes
836        let mut bytes = vec![0u8; 10]; // Not a multiple of signature length
837        // Set bitmap to indicate 1 signature (bit 0 set)
838        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)); // Out of bounds
857    }
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)]); // Index 32 is out of bounds
956        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        // Invalid length (not a multiple of ED25519_PUBLIC_KEY_LENGTH + 1 for threshold)
973        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}