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