Skip to main content

aptos_sdk/crypto/
multi_key.rs

1//! `MultiKey` signature scheme implementation.
2//!
3//! `MultiKey` enables M-of-N threshold signatures with mixed key types.
4//! Unlike `MultiEd25519`, each key can be a different signature scheme
5//! (Ed25519, Secp256k1, Secp256r1, etc.).
6
7use crate::error::{AptosError, AptosResult};
8use serde::{Deserialize, Serialize};
9use std::fmt;
10
11/// Maximum number of keys in a multi-key account.
12pub const MAX_NUM_OF_KEYS: usize = 32;
13
14// Compile-time assertion: MAX_NUM_OF_KEYS must fit in u8 for bitmap operations
15const _: () = assert!(MAX_NUM_OF_KEYS <= u8::MAX as usize);
16
17/// Minimum threshold (at least 1 signature required).
18pub const MIN_THRESHOLD: u8 = 1;
19
20/// Supported signature schemes for multi-key.
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[repr(u8)]
23pub enum AnyPublicKeyVariant {
24    /// Ed25519 public key.
25    Ed25519 = 0,
26    /// Secp256k1 ECDSA public key.
27    Secp256k1 = 1,
28    /// Secp256r1 (P-256) ECDSA public key.
29    Secp256r1 = 2,
30    /// Keyless public key.
31    Keyless = 3,
32}
33
34impl AnyPublicKeyVariant {
35    /// Get the variant from a byte.
36    ///
37    /// # Errors
38    ///
39    /// Returns [`AptosError::InvalidPublicKey`] if the byte value is not a valid variant (0-3).
40    pub fn from_byte(byte: u8) -> AptosResult<Self> {
41        match byte {
42            0 => Ok(Self::Ed25519),
43            1 => Ok(Self::Secp256k1),
44            2 => Ok(Self::Secp256r1),
45            3 => Ok(Self::Keyless),
46            _ => Err(AptosError::InvalidPublicKey(format!(
47                "unknown public key variant: {byte}"
48            ))),
49        }
50    }
51
52    /// Get the byte representation.
53    pub fn as_byte(&self) -> u8 {
54        *self as u8
55    }
56}
57
58/// A public key that can be any supported signature scheme.
59#[derive(Clone, PartialEq, Eq)]
60pub struct AnyPublicKey {
61    /// The signature scheme variant.
62    pub variant: AnyPublicKeyVariant,
63    /// The raw public key bytes.
64    pub bytes: Vec<u8>,
65}
66
67impl AnyPublicKey {
68    /// Creates a new `AnyPublicKey`.
69    pub fn new(variant: AnyPublicKeyVariant, bytes: Vec<u8>) -> Self {
70        Self { variant, bytes }
71    }
72
73    /// Creates an Ed25519 public key.
74    #[cfg(feature = "ed25519")]
75    pub fn ed25519(public_key: &crate::crypto::Ed25519PublicKey) -> Self {
76        Self {
77            variant: AnyPublicKeyVariant::Ed25519,
78            bytes: public_key.to_bytes().to_vec(),
79        }
80    }
81
82    /// Creates a Secp256k1 public key.
83    /// Uses uncompressed format (65 bytes) as required by the Aptos protocol.
84    #[cfg(feature = "secp256k1")]
85    pub fn secp256k1(public_key: &crate::crypto::Secp256k1PublicKey) -> Self {
86        Self {
87            variant: AnyPublicKeyVariant::Secp256k1,
88            bytes: public_key.to_uncompressed_bytes(),
89        }
90    }
91
92    /// Creates a Secp256r1 public key.
93    /// Uses uncompressed format (65 bytes) as required by the Aptos protocol.
94    #[cfg(feature = "secp256r1")]
95    pub fn secp256r1(public_key: &crate::crypto::Secp256r1PublicKey) -> Self {
96        Self {
97            variant: AnyPublicKeyVariant::Secp256r1,
98            bytes: public_key.to_uncompressed_bytes(),
99        }
100    }
101
102    /// Serializes to BCS format: `variant_byte` || ULEB128(length) || bytes
103    ///
104    /// This is the correct BCS serialization format for `AnyPublicKey` used
105    /// in authentication key derivation: `SHA3-256(BCS(AnyPublicKey) || scheme_id)`
106    pub fn to_bcs_bytes(&self) -> Vec<u8> {
107        let mut result = Vec::with_capacity(1 + 1 + self.bytes.len());
108        result.push(self.variant.as_byte());
109        // BCS uses ULEB128 for vector lengths
110        result.extend(uleb128_encode(self.bytes.len()));
111        result.extend_from_slice(&self.bytes);
112        result
113    }
114
115    /// Verifies a signature against a message.
116    ///
117    /// # Errors
118    ///
119    /// This function will return an error if:
120    /// - The signature variant doesn't match the public key variant
121    /// - The public key bytes are invalid for the variant
122    /// - The signature bytes are invalid for the variant
123    /// - Signature verification fails
124    /// - Verification is not supported for the variant
125    #[allow(unused_variables)]
126    pub fn verify(&self, message: &[u8], signature: &AnySignature) -> AptosResult<()> {
127        if signature.variant != self.variant {
128            return Err(AptosError::InvalidSignature(format!(
129                "signature variant {:?} doesn't match public key variant {:?}",
130                signature.variant, self.variant
131            )));
132        }
133
134        match self.variant {
135            #[cfg(feature = "ed25519")]
136            AnyPublicKeyVariant::Ed25519 => {
137                let pk = crate::crypto::Ed25519PublicKey::from_bytes(&self.bytes)?;
138                let sig = crate::crypto::Ed25519Signature::from_bytes(&signature.bytes)?;
139                pk.verify(message, &sig)
140            }
141            #[cfg(feature = "secp256k1")]
142            AnyPublicKeyVariant::Secp256k1 => {
143                // Public key can be either compressed (33 bytes) or uncompressed (65 bytes)
144                let pk = crate::crypto::Secp256k1PublicKey::from_bytes(&self.bytes)?;
145                let sig = crate::crypto::Secp256k1Signature::from_bytes(&signature.bytes)?;
146                pk.verify(message, &sig)
147            }
148            #[cfg(feature = "secp256r1")]
149            AnyPublicKeyVariant::Secp256r1 => {
150                // Public key can be either compressed (33 bytes) or uncompressed (65 bytes)
151                let pk = crate::crypto::Secp256r1PublicKey::from_bytes(&self.bytes)?;
152                let sig = crate::crypto::Secp256r1Signature::from_bytes(&signature.bytes)?;
153                pk.verify(message, &sig)
154            }
155            #[allow(unreachable_patterns)]
156            _ => Err(AptosError::InvalidPublicKey(format!(
157                "verification not supported for variant {:?}",
158                self.variant
159            ))),
160        }
161    }
162}
163
164impl fmt::Debug for AnyPublicKey {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        write!(
167            f,
168            "AnyPublicKey({:?}, {})",
169            self.variant,
170            const_hex::encode_prefixed(&self.bytes)
171        )
172    }
173}
174
175impl fmt::Display for AnyPublicKey {
176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177        write!(
178            f,
179            "{:?}:{}",
180            self.variant,
181            const_hex::encode_prefixed(&self.bytes)
182        )
183    }
184}
185
186/// A signature that can be any supported signature scheme.
187#[derive(Clone, PartialEq, Eq)]
188pub struct AnySignature {
189    /// The signature scheme variant.
190    pub variant: AnyPublicKeyVariant,
191    /// The raw signature bytes.
192    pub bytes: Vec<u8>,
193}
194
195impl AnySignature {
196    /// Creates a new `AnySignature`.
197    pub fn new(variant: AnyPublicKeyVariant, bytes: Vec<u8>) -> Self {
198        Self { variant, bytes }
199    }
200
201    /// Creates an Ed25519 signature.
202    #[cfg(feature = "ed25519")]
203    pub fn ed25519(signature: &crate::crypto::Ed25519Signature) -> Self {
204        Self {
205            variant: AnyPublicKeyVariant::Ed25519,
206            bytes: signature.to_bytes().to_vec(),
207        }
208    }
209
210    /// Creates a Secp256k1 signature.
211    #[cfg(feature = "secp256k1")]
212    pub fn secp256k1(signature: &crate::crypto::Secp256k1Signature) -> Self {
213        Self {
214            variant: AnyPublicKeyVariant::Secp256k1,
215            bytes: signature.to_bytes().to_vec(),
216        }
217    }
218
219    /// Creates a Secp256r1 signature.
220    #[cfg(feature = "secp256r1")]
221    pub fn secp256r1(signature: &crate::crypto::Secp256r1Signature) -> Self {
222        Self {
223            variant: AnyPublicKeyVariant::Secp256r1,
224            bytes: signature.to_bytes().to_vec(),
225        }
226    }
227
228    /// Serializes to BCS format: `variant_byte` || ULEB128(length) || bytes
229    pub fn to_bcs_bytes(&self) -> Vec<u8> {
230        let mut result = Vec::with_capacity(1 + 1 + self.bytes.len());
231        result.push(self.variant.as_byte());
232        // BCS uses ULEB128 for vector lengths
233        result.extend(uleb128_encode(self.bytes.len()));
234        result.extend_from_slice(&self.bytes);
235        result
236    }
237}
238
239/// Encodes a value as `ULEB128` (unsigned `LEB128`).
240/// BCS uses `ULEB128` for encoding vector/sequence lengths.
241/// For typical sizes (< 128), this returns a single byte.
242#[allow(clippy::cast_possible_truncation)] // value & 0x7F is always <= 127
243#[inline]
244fn uleb128_encode(mut value: usize) -> Vec<u8> {
245    // Pre-allocate for common case: values < 128 need 1 byte, < 16384 need 2 bytes
246    let mut result = Vec::with_capacity(if value < 128 { 1 } else { 2 });
247    loop {
248        let byte = (value & 0x7F) as u8;
249        value >>= 7;
250        if value == 0 {
251            result.push(byte);
252            break;
253        }
254        result.push(byte | 0x80);
255    }
256    result
257}
258
259/// Decodes a `ULEB128` value from bytes, returning `(value, bytes_consumed)`.
260fn uleb128_decode(bytes: &[u8]) -> Option<(usize, usize)> {
261    let mut result: usize = 0;
262    let mut shift = 0;
263    for (i, &byte) in bytes.iter().enumerate() {
264        result |= ((byte & 0x7F) as usize) << shift;
265        if byte & 0x80 == 0 {
266            return Some((result, i + 1));
267        }
268        shift += 7;
269        if shift >= 64 {
270            return None; // Overflow
271        }
272    }
273    None
274}
275
276impl fmt::Debug for AnySignature {
277    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278        write!(
279            f,
280            "AnySignature({:?}, {} bytes)",
281            self.variant,
282            self.bytes.len()
283        )
284    }
285}
286
287/// A multi-key public key supporting mixed signature schemes.
288///
289/// This allows M-of-N threshold signing where each key can be a different type.
290#[derive(Clone, PartialEq, Eq)]
291pub struct MultiKeyPublicKey {
292    /// The individual public keys.
293    public_keys: Vec<AnyPublicKey>,
294    /// The required threshold (M in M-of-N).
295    threshold: u8,
296}
297
298impl MultiKeyPublicKey {
299    /// Creates a new multi-key public key.
300    ///
301    /// # Arguments
302    ///
303    /// * `public_keys` - The individual public keys (can be mixed types)
304    /// * `threshold` - The number of signatures required (M in M-of-N)
305    ///
306    /// # Errors
307    ///
308    /// Returns [`AptosError::InvalidPublicKey`] if:
309    /// - No public keys are provided
310    /// - More than 32 public keys are provided
311    /// - Threshold is 0
312    /// - Threshold exceeds the number of keys
313    pub fn new(public_keys: Vec<AnyPublicKey>, threshold: u8) -> AptosResult<Self> {
314        if public_keys.is_empty() {
315            return Err(AptosError::InvalidPublicKey(
316                "multi-key requires at least one public key".into(),
317            ));
318        }
319        if public_keys.len() > MAX_NUM_OF_KEYS {
320            return Err(AptosError::InvalidPublicKey(format!(
321                "multi-key supports at most {} keys, got {}",
322                MAX_NUM_OF_KEYS,
323                public_keys.len()
324            )));
325        }
326        if threshold < MIN_THRESHOLD {
327            return Err(AptosError::InvalidPublicKey(
328                "threshold must be at least 1".into(),
329            ));
330        }
331        if threshold as usize > public_keys.len() {
332            return Err(AptosError::InvalidPublicKey(format!(
333                "threshold {} exceeds number of keys {}",
334                threshold,
335                public_keys.len()
336            )));
337        }
338        Ok(Self {
339            public_keys,
340            threshold,
341        })
342    }
343
344    /// Returns the number of public keys.
345    pub fn num_keys(&self) -> usize {
346        self.public_keys.len()
347    }
348
349    /// Returns the threshold.
350    pub fn threshold(&self) -> u8 {
351        self.threshold
352    }
353
354    /// Returns the individual public keys.
355    pub fn public_keys(&self) -> &[AnyPublicKey] {
356        &self.public_keys
357    }
358
359    /// Returns the key at the given index.
360    pub fn get(&self, index: usize) -> Option<&AnyPublicKey> {
361        self.public_keys.get(index)
362    }
363
364    /// Serializes to bytes for authentication key derivation.
365    ///
366    /// Format: `num_keys` || `pk1_bcs` || `pk2_bcs` || ... || threshold
367    #[allow(clippy::cast_possible_truncation)] // public_keys.len() <= MAX_NUM_OF_KEYS (32)
368    pub fn to_bytes(&self) -> Vec<u8> {
369        // Pre-allocate: 1 byte num_keys + estimated key size (avg ~35 bytes per key) + 1 byte threshold
370        let estimated_size = 2 + self.public_keys.len() * 36;
371        let mut bytes = Vec::with_capacity(estimated_size);
372
373        // Number of keys (1 byte, validated in new())
374        bytes.push(self.public_keys.len() as u8);
375
376        // Each public key in BCS format
377        for pk in &self.public_keys {
378            bytes.extend(pk.to_bcs_bytes());
379        }
380
381        // Threshold (1 byte)
382        bytes.push(self.threshold);
383
384        bytes
385    }
386
387    /// Creates from bytes.
388    ///
389    /// # Errors
390    ///
391    /// Returns [`AptosError::InvalidPublicKey`] if:
392    /// - The bytes are empty
393    /// - The number of keys is invalid (0 or > 32)
394    /// - The bytes are too short for the expected structure
395    /// - Any public key variant byte is invalid
396    /// - Any public key length or data is invalid
397    /// - The threshold is invalid
398    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
399        // SECURITY: Limit individual key size to prevent DoS via large allocations
400        // Largest supported key is uncompressed secp256k1/secp256r1 at 65 bytes
401        const MAX_KEY_SIZE: usize = 128;
402
403        if bytes.is_empty() {
404            return Err(AptosError::InvalidPublicKey("empty bytes".into()));
405        }
406
407        let num_keys = bytes[0] as usize;
408        if num_keys == 0 || num_keys > MAX_NUM_OF_KEYS {
409            return Err(AptosError::InvalidPublicKey(format!(
410                "invalid number of keys: {num_keys}"
411            )));
412        }
413
414        let mut offset = 1;
415        let mut public_keys = Vec::with_capacity(num_keys);
416
417        for _ in 0..num_keys {
418            if offset >= bytes.len() {
419                return Err(AptosError::InvalidPublicKey("bytes too short".into()));
420            }
421
422            let variant = AnyPublicKeyVariant::from_byte(bytes[offset])?;
423            offset += 1;
424
425            // Decode ULEB128 length
426            let (len, len_bytes) = uleb128_decode(&bytes[offset..]).ok_or_else(|| {
427                AptosError::InvalidPublicKey("invalid ULEB128 length encoding".into())
428            })?;
429            offset += len_bytes;
430
431            if len > MAX_KEY_SIZE {
432                return Err(AptosError::InvalidPublicKey(format!(
433                    "key size {len} exceeds maximum {MAX_KEY_SIZE}"
434                )));
435            }
436
437            if offset + len > bytes.len() {
438                return Err(AptosError::InvalidPublicKey(
439                    "bytes too short for key".into(),
440                ));
441            }
442
443            let key_bytes = bytes[offset..offset + len].to_vec();
444            offset += len;
445
446            public_keys.push(AnyPublicKey::new(variant, key_bytes));
447        }
448
449        if offset >= bytes.len() {
450            return Err(AptosError::InvalidPublicKey(
451                "bytes too short for threshold".into(),
452            ));
453        }
454
455        let threshold = bytes[offset];
456
457        Self::new(public_keys, threshold)
458    }
459
460    /// Derives the account address for this multi-key public key.
461    pub fn to_address(&self) -> crate::types::AccountAddress {
462        crate::crypto::derive_address(&self.to_bytes(), crate::crypto::MULTI_KEY_SCHEME)
463    }
464
465    /// Derives the authentication key for this public key.
466    pub fn to_authentication_key(&self) -> [u8; 32] {
467        crate::crypto::derive_authentication_key(&self.to_bytes(), crate::crypto::MULTI_KEY_SCHEME)
468    }
469
470    /// Verifies a multi-key signature against a message.
471    ///
472    /// # Errors
473    ///
474    /// This function will return an error if:
475    /// - The number of signatures is less than the threshold
476    /// - Any individual signature verification fails
477    /// - A signer index is out of bounds
478    pub fn verify(&self, message: &[u8], signature: &MultiKeySignature) -> AptosResult<()> {
479        // Check that we have enough signatures
480        if signature.num_signatures() < self.threshold as usize {
481            return Err(AptosError::SignatureVerificationFailed);
482        }
483
484        // Verify each signature
485        for (index, sig) in signature.signatures() {
486            if *index as usize >= self.public_keys.len() {
487                return Err(AptosError::InvalidSignature(format!(
488                    "signer index {} out of bounds (max {})",
489                    index,
490                    self.public_keys.len() - 1
491                )));
492            }
493            let pk = &self.public_keys[*index as usize];
494            pk.verify(message, sig)?;
495        }
496
497        Ok(())
498    }
499}
500
501impl fmt::Debug for MultiKeyPublicKey {
502    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503        write!(
504            f,
505            "MultiKeyPublicKey({}-of-{} keys)",
506            self.threshold,
507            self.public_keys.len()
508        )
509    }
510}
511
512impl fmt::Display for MultiKeyPublicKey {
513    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514        f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
515    }
516}
517
518/// A multi-key signature containing signatures from multiple signers.
519#[derive(Clone, PartialEq, Eq)]
520pub struct MultiKeySignature {
521    /// Individual signatures with their signer index.
522    signatures: Vec<(u8, AnySignature)>,
523    /// Bitmap indicating which keys signed (little-endian, up to 4 bytes for 32 keys).
524    bitmap: [u8; 4],
525}
526
527impl MultiKeySignature {
528    /// Creates a new multi-key signature from individual signatures.
529    ///
530    /// # Arguments
531    ///
532    /// * `signatures` - Vec of (`signer_index`, signature) pairs
533    ///
534    /// # Errors
535    ///
536    /// Returns [`AptosError::InvalidSignature`] if:
537    /// - No signatures are provided
538    /// - More than 32 signatures are provided
539    /// - A signer index is out of bounds (>= 32)
540    /// - Duplicate signer indices are present
541    pub fn new(mut signatures: Vec<(u8, AnySignature)>) -> AptosResult<Self> {
542        if signatures.is_empty() {
543            return Err(AptosError::InvalidSignature(
544                "multi-key signature requires at least one signature".into(),
545            ));
546        }
547        if signatures.len() > MAX_NUM_OF_KEYS {
548            return Err(AptosError::InvalidSignature(format!(
549                "too many signatures: {} (max {})",
550                signatures.len(),
551                MAX_NUM_OF_KEYS
552            )));
553        }
554
555        // Sort by index
556        signatures.sort_by_key(|(idx, _)| *idx);
557
558        // Check for duplicates and bounds, build bitmap
559        let mut bitmap = [0u8; 4];
560        let mut last_index: Option<u8> = None;
561
562        for (index, _) in &signatures {
563            if *index as usize >= MAX_NUM_OF_KEYS {
564                return Err(AptosError::InvalidSignature(format!(
565                    "signer index {} out of bounds (max {})",
566                    index,
567                    MAX_NUM_OF_KEYS - 1
568                )));
569            }
570            if last_index == Some(*index) {
571                return Err(AptosError::InvalidSignature(format!(
572                    "duplicate signer index {index}"
573                )));
574            }
575            last_index = Some(*index);
576
577            // Set bit in bitmap
578            let byte_index = (index / 8) as usize;
579            let bit_index = index % 8;
580            bitmap[byte_index] |= 1 << bit_index;
581        }
582
583        Ok(Self { signatures, bitmap })
584    }
585
586    /// Returns the number of signatures.
587    pub fn num_signatures(&self) -> usize {
588        self.signatures.len()
589    }
590
591    /// Returns the individual signatures with their indices.
592    pub fn signatures(&self) -> &[(u8, AnySignature)] {
593        &self.signatures
594    }
595
596    /// Returns the signer bitmap.
597    pub fn bitmap(&self) -> &[u8; 4] {
598        &self.bitmap
599    }
600
601    /// Checks if a particular index signed.
602    pub fn has_signature(&self, index: u8) -> bool {
603        if index as usize >= MAX_NUM_OF_KEYS {
604            return false;
605        }
606        let byte_index = (index / 8) as usize;
607        let bit_index = index % 8;
608        (self.bitmap[byte_index] >> bit_index) & 1 == 1
609    }
610
611    /// Serializes to bytes.
612    ///
613    /// Format: `num_signatures` || `sig1_bcs` || `sig2_bcs` || ... || bitmap (4 bytes)
614    #[allow(clippy::cast_possible_truncation)] // signatures.len() <= MAX_NUM_OF_KEYS (32)
615    pub fn to_bytes(&self) -> Vec<u8> {
616        // Pre-allocate: 1 byte num_sigs + estimated sig size (avg ~66 bytes per sig) + 4 bytes bitmap
617        let estimated_size = 5 + self.signatures.len() * 68;
618        let mut bytes = Vec::with_capacity(estimated_size);
619
620        // Number of signatures (validated in new())
621        bytes.push(self.signatures.len() as u8);
622
623        // Each signature in BCS format (ordered by index)
624        for (_, sig) in &self.signatures {
625            bytes.extend(sig.to_bcs_bytes());
626        }
627
628        // Bitmap (4 bytes)
629        bytes.extend_from_slice(&self.bitmap);
630
631        bytes
632    }
633
634    /// Creates from bytes.
635    ///
636    /// # Errors
637    ///
638    /// Returns [`AptosError::InvalidSignature`] if:
639    /// - The bytes are too short (less than 5 bytes for `num_sigs` + bitmap)
640    /// - The number of signatures is invalid (0 or > 32)
641    /// - The bitmap doesn't match the number of signatures
642    /// - The bytes are too short for the expected structure
643    /// - Any signature variant byte is invalid
644    /// - Any signature length or data is invalid
645    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
646        // SECURITY: Limit individual signature size to prevent DoS via large allocations
647        // Largest supported signature is ~72 bytes for ECDSA DER format
648        const MAX_SIGNATURE_SIZE: usize = 128;
649
650        if bytes.len() < 5 {
651            return Err(AptosError::InvalidSignature("bytes too short".into()));
652        }
653
654        let num_sigs = bytes[0] as usize;
655        if num_sigs == 0 || num_sigs > MAX_NUM_OF_KEYS {
656            return Err(AptosError::InvalidSignature(format!(
657                "invalid number of signatures: {num_sigs}"
658            )));
659        }
660
661        // Read bitmap from the end
662        let bitmap_start = bytes.len() - 4;
663        let mut bitmap = [0u8; 4];
664        bitmap.copy_from_slice(&bytes[bitmap_start..]);
665
666        // Parse signatures
667        let mut offset = 1;
668        let mut signatures = Vec::with_capacity(num_sigs);
669
670        // Determine signer indices from bitmap (MAX_NUM_OF_KEYS is 32, fits in u8)
671        let mut signer_indices = Vec::new();
672        #[allow(clippy::cast_possible_truncation)]
673        for bit_pos in 0..(MAX_NUM_OF_KEYS as u8) {
674            let byte_idx = (bit_pos / 8) as usize;
675            let bit_idx = bit_pos % 8;
676            if (bitmap[byte_idx] >> bit_idx) & 1 == 1 {
677                signer_indices.push(bit_pos);
678            }
679        }
680
681        if signer_indices.len() != num_sigs {
682            return Err(AptosError::InvalidSignature(
683                "bitmap doesn't match number of signatures".into(),
684            ));
685        }
686
687        for &index in &signer_indices {
688            if offset >= bitmap_start {
689                return Err(AptosError::InvalidSignature("bytes too short".into()));
690            }
691
692            let variant = AnyPublicKeyVariant::from_byte(bytes[offset])?;
693            offset += 1;
694
695            // Decode ULEB128 length
696            let (len, len_bytes) =
697                uleb128_decode(&bytes[offset..bitmap_start]).ok_or_else(|| {
698                    AptosError::InvalidSignature("invalid ULEB128 length encoding".into())
699                })?;
700            offset += len_bytes;
701
702            if len > MAX_SIGNATURE_SIZE {
703                return Err(AptosError::InvalidSignature(format!(
704                    "signature size {len} exceeds maximum {MAX_SIGNATURE_SIZE}"
705                )));
706            }
707
708            if offset + len > bitmap_start {
709                return Err(AptosError::InvalidSignature(
710                    "bytes too short for signature".into(),
711                ));
712            }
713
714            let sig_bytes = bytes[offset..offset + len].to_vec();
715            offset += len;
716
717            signatures.push((index, AnySignature::new(variant, sig_bytes)));
718        }
719
720        Ok(Self { signatures, bitmap })
721    }
722}
723
724impl fmt::Debug for MultiKeySignature {
725    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
726        write!(
727            f,
728            "MultiKeySignature({} signatures, bitmap={:?})",
729            self.signatures.len(),
730            self.bitmap
731        )
732    }
733}
734
735impl fmt::Display for MultiKeySignature {
736    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
737        f.write_str(&const_hex::encode_prefixed(self.to_bytes()))
738    }
739}
740
741#[cfg(test)]
742mod tests {
743    use super::*;
744
745    #[test]
746    fn test_any_public_key_variant_from_byte() {
747        assert_eq!(
748            AnyPublicKeyVariant::from_byte(0).unwrap(),
749            AnyPublicKeyVariant::Ed25519
750        );
751        assert_eq!(
752            AnyPublicKeyVariant::from_byte(1).unwrap(),
753            AnyPublicKeyVariant::Secp256k1
754        );
755        assert_eq!(
756            AnyPublicKeyVariant::from_byte(2).unwrap(),
757            AnyPublicKeyVariant::Secp256r1
758        );
759        assert_eq!(
760            AnyPublicKeyVariant::from_byte(3).unwrap(),
761            AnyPublicKeyVariant::Keyless
762        );
763        assert!(AnyPublicKeyVariant::from_byte(4).is_err());
764        assert!(AnyPublicKeyVariant::from_byte(255).is_err());
765    }
766
767    #[test]
768    fn test_any_public_key_variant_as_byte() {
769        assert_eq!(AnyPublicKeyVariant::Ed25519.as_byte(), 0);
770        assert_eq!(AnyPublicKeyVariant::Secp256k1.as_byte(), 1);
771        assert_eq!(AnyPublicKeyVariant::Secp256r1.as_byte(), 2);
772        assert_eq!(AnyPublicKeyVariant::Keyless.as_byte(), 3);
773    }
774
775    #[test]
776    fn test_any_public_key_new() {
777        let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0x11; 32]);
778        assert_eq!(pk.variant, AnyPublicKeyVariant::Ed25519);
779        assert_eq!(pk.bytes.len(), 32);
780        assert_eq!(pk.bytes[0], 0x11);
781    }
782
783    #[test]
784    fn test_any_public_key_to_bcs_bytes() {
785        let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0xaa; 32]);
786        let bcs = pk.to_bcs_bytes();
787
788        // Format: variant_byte || ULEB128(length) || bytes
789        assert_eq!(bcs[0], 0); // Ed25519 variant
790        assert_eq!(bcs[1], 32); // ULEB128(32) = 0x20 (since 32 < 128)
791        assert_eq!(bcs[2], 0xaa); // first byte of key
792        assert_eq!(bcs.len(), 1 + 1 + 32); // variant + length + bytes
793    }
794
795    #[test]
796    fn test_any_public_key_debug() {
797        let pk = AnyPublicKey::new(AnyPublicKeyVariant::Secp256k1, vec![0xbb; 33]);
798        let debug = format!("{pk:?}");
799        assert!(debug.contains("Secp256k1"));
800        assert!(debug.contains("0x"));
801    }
802
803    #[test]
804    fn test_any_signature_new() {
805        let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xcc; 64]);
806        assert_eq!(sig.variant, AnyPublicKeyVariant::Ed25519);
807        assert_eq!(sig.bytes.len(), 64);
808    }
809
810    #[test]
811    fn test_any_signature_to_bcs_bytes() {
812        let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xdd; 64]);
813        let bcs = sig.to_bcs_bytes();
814
815        // Format: variant_byte || ULEB128(length) || bytes
816        assert_eq!(bcs[0], 0); // Ed25519 variant
817        assert_eq!(bcs[1], 64); // ULEB128(64) = 0x40 (since 64 < 128)
818        assert_eq!(bcs[2], 0xdd); // first byte of signature
819        assert_eq!(bcs.len(), 1 + 1 + 64); // variant + length + bytes
820    }
821
822    #[test]
823    fn test_any_signature_debug() {
824        let sig = AnySignature::new(AnyPublicKeyVariant::Secp256r1, vec![0xee; 64]);
825        let debug = format!("{sig:?}");
826        assert!(debug.contains("Secp256r1"));
827        assert!(debug.contains("64 bytes"));
828    }
829
830    #[test]
831    fn test_any_public_key_verify_mismatched_variant() {
832        let pk = AnyPublicKey::new(AnyPublicKeyVariant::Ed25519, vec![0; 32]);
833        let sig = AnySignature::new(AnyPublicKeyVariant::Secp256k1, vec![0; 64]);
834
835        let result = pk.verify(b"message", &sig);
836        assert!(result.is_err());
837        assert!(result.unwrap_err().to_string().contains("variant"));
838    }
839
840    #[test]
841    fn test_multi_key_signature_insufficient_sigs() {
842        // Empty signatures should fail
843        let result = MultiKeySignature::new(vec![]);
844        assert!(result.is_err());
845    }
846
847    #[test]
848    fn test_multi_key_signature_duplicate_indices() {
849        let sig1 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
850        let sig2 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![1; 64]);
851
852        // Duplicate index should fail
853        let result = MultiKeySignature::new(vec![(0, sig1.clone()), (0, sig2)]);
854        assert!(result.is_err());
855    }
856
857    #[test]
858    fn test_multi_key_signature_index_out_of_range() {
859        let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
860
861        // Index 32 is out of range (0-31)
862        let result = MultiKeySignature::new(vec![(32, sig)]);
863        assert!(result.is_err());
864    }
865
866    #[test]
867    fn test_multi_key_signature_basic() {
868        let sig1 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xaa; 64]);
869        let sig2 = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0xbb; 64]);
870
871        let multi_sig = MultiKeySignature::new(vec![(0, sig1), (5, sig2)]).unwrap();
872
873        assert_eq!(multi_sig.num_signatures(), 2);
874        assert!(multi_sig.has_signature(0));
875        assert!(!multi_sig.has_signature(1));
876        assert!(multi_sig.has_signature(5));
877    }
878
879    #[test]
880    fn test_multi_key_signature_debug_display() {
881        let sig = AnySignature::new(AnyPublicKeyVariant::Ed25519, vec![0; 64]);
882        let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
883
884        let debug = format!("{multi_sig:?}");
885        let display = format!("{multi_sig}");
886
887        assert!(debug.contains("MultiKeySignature"));
888        assert!(display.starts_with("0x"));
889    }
890
891    #[test]
892    #[cfg(feature = "ed25519")]
893    fn test_multi_key_public_key_creation() {
894        use crate::crypto::Ed25519PrivateKey;
895
896        let keys: Vec<_> = (0..3)
897            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
898            .collect();
899
900        // Valid 2-of-3
901        let multi_pk = MultiKeyPublicKey::new(keys.clone(), 2).unwrap();
902        assert_eq!(multi_pk.num_keys(), 3);
903        assert_eq!(multi_pk.threshold(), 2);
904
905        // Invalid: threshold > num_keys
906        assert!(MultiKeyPublicKey::new(keys.clone(), 4).is_err());
907
908        // Invalid: threshold = 0
909        assert!(MultiKeyPublicKey::new(keys.clone(), 0).is_err());
910
911        // Invalid: empty keys
912        assert!(MultiKeyPublicKey::new(vec![], 1).is_err());
913    }
914
915    #[test]
916    #[cfg(all(feature = "ed25519", feature = "secp256k1"))]
917    fn test_multi_key_mixed_types() {
918        use crate::crypto::{Ed25519PrivateKey, Secp256k1PrivateKey};
919
920        // Create mixed key types
921        let ed_key = AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key());
922        let secp_key = AnyPublicKey::secp256k1(&Secp256k1PrivateKey::generate().public_key());
923
924        let multi_pk = MultiKeyPublicKey::new(vec![ed_key, secp_key], 2).unwrap();
925        assert_eq!(multi_pk.num_keys(), 2);
926        assert_eq!(
927            multi_pk.get(0).unwrap().variant,
928            AnyPublicKeyVariant::Ed25519
929        );
930        assert_eq!(
931            multi_pk.get(1).unwrap().variant,
932            AnyPublicKeyVariant::Secp256k1
933        );
934    }
935
936    #[test]
937    #[cfg(feature = "ed25519")]
938    fn test_multi_key_sign_verify() {
939        use crate::crypto::Ed25519PrivateKey;
940
941        let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
942        let public_keys: Vec<_> = private_keys
943            .iter()
944            .map(|k| AnyPublicKey::ed25519(&k.public_key()))
945            .collect();
946
947        let multi_pk = MultiKeyPublicKey::new(public_keys, 2).unwrap();
948        let message = b"test message";
949
950        // Sign with keys 0 and 2 (2-of-3)
951        let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
952        let sig2 = AnySignature::ed25519(&private_keys[2].sign(message));
953
954        let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
955
956        // Verify should succeed
957        assert!(multi_pk.verify(message, &multi_sig).is_ok());
958
959        // Wrong message should fail
960        assert!(multi_pk.verify(b"wrong message", &multi_sig).is_err());
961    }
962
963    #[test]
964    #[cfg(feature = "ed25519")]
965    fn test_multi_key_bytes_roundtrip() {
966        use crate::crypto::Ed25519PrivateKey;
967
968        let keys: Vec<_> = (0..3)
969            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
970            .collect();
971        let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
972
973        let bytes = multi_pk.to_bytes();
974        let restored = MultiKeyPublicKey::from_bytes(&bytes).unwrap();
975
976        assert_eq!(multi_pk.threshold(), restored.threshold());
977        assert_eq!(multi_pk.num_keys(), restored.num_keys());
978    }
979
980    #[test]
981    #[cfg(feature = "ed25519")]
982    fn test_multi_key_signature_bytes_roundtrip() {
983        use crate::crypto::Ed25519PrivateKey;
984
985        let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
986        let message = b"test";
987
988        let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
989        let sig2 = AnySignature::ed25519(&private_keys[2].sign(message));
990
991        let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
992
993        let bytes = multi_sig.to_bytes();
994        let restored = MultiKeySignature::from_bytes(&bytes).unwrap();
995
996        assert_eq!(multi_sig.num_signatures(), restored.num_signatures());
997        assert_eq!(multi_sig.bitmap(), restored.bitmap());
998    }
999
1000    #[test]
1001    #[cfg(feature = "ed25519")]
1002    fn test_signature_bitmap() {
1003        use crate::crypto::Ed25519PrivateKey;
1004
1005        let private_keys: Vec<_> = (0..5).map(|_| Ed25519PrivateKey::generate()).collect();
1006        let message = b"test";
1007
1008        // Sign with indices 1, 3, 4
1009        let signatures: Vec<_> = [1, 3, 4]
1010            .iter()
1011            .map(|&i| {
1012                (
1013                    i,
1014                    AnySignature::ed25519(&private_keys[i as usize].sign(message)),
1015                )
1016            })
1017            .collect();
1018
1019        let multi_sig = MultiKeySignature::new(signatures).unwrap();
1020
1021        assert!(!multi_sig.has_signature(0));
1022        assert!(multi_sig.has_signature(1));
1023        assert!(!multi_sig.has_signature(2));
1024        assert!(multi_sig.has_signature(3));
1025        assert!(multi_sig.has_signature(4));
1026        assert!(!multi_sig.has_signature(5));
1027    }
1028
1029    #[test]
1030    fn test_multi_key_public_key_empty_keys() {
1031        let result = MultiKeyPublicKey::new(vec![], 1);
1032        assert!(result.is_err());
1033        assert!(result.unwrap_err().to_string().contains("at least one"));
1034    }
1035
1036    #[test]
1037    #[cfg(feature = "ed25519")]
1038    fn test_multi_key_public_key_threshold_zero() {
1039        use crate::crypto::Ed25519PrivateKey;
1040
1041        let keys: Vec<_> = (0..2)
1042            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1043            .collect();
1044        let result = MultiKeyPublicKey::new(keys, 0);
1045        assert!(result.is_err());
1046        assert!(result.unwrap_err().to_string().contains("at least 1"));
1047    }
1048
1049    #[test]
1050    #[cfg(feature = "ed25519")]
1051    fn test_multi_key_public_key_threshold_exceeds() {
1052        use crate::crypto::Ed25519PrivateKey;
1053
1054        let keys: Vec<_> = (0..2)
1055            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1056            .collect();
1057        let result = MultiKeyPublicKey::new(keys, 5);
1058        assert!(result.is_err());
1059        assert!(result.unwrap_err().to_string().contains("exceed"));
1060    }
1061
1062    #[test]
1063    #[cfg(feature = "ed25519")]
1064    fn test_multi_key_signature_empty() {
1065        let result = MultiKeySignature::new(vec![]);
1066        assert!(result.is_err());
1067        assert!(result.unwrap_err().to_string().contains("at least one"));
1068    }
1069
1070    #[test]
1071    #[cfg(feature = "ed25519")]
1072    fn test_multi_key_signature_duplicate_index() {
1073        use crate::crypto::Ed25519PrivateKey;
1074
1075        let private_key = Ed25519PrivateKey::generate();
1076        let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1077
1078        let result = MultiKeySignature::new(vec![(0, sig.clone()), (0, sig)]);
1079        assert!(result.is_err());
1080        assert!(result.unwrap_err().to_string().contains("duplicate"));
1081    }
1082
1083    #[test]
1084    #[cfg(feature = "ed25519")]
1085    fn test_multi_key_public_key_accessors() {
1086        use crate::crypto::Ed25519PrivateKey;
1087
1088        let keys: Vec<_> = (0..3)
1089            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1090            .collect();
1091        let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1092
1093        assert_eq!(multi_pk.threshold(), 2);
1094        assert_eq!(multi_pk.num_keys(), 3);
1095        assert_eq!(multi_pk.public_keys().len(), 3);
1096    }
1097
1098    #[test]
1099    #[cfg(feature = "ed25519")]
1100    fn test_multi_key_signature_accessors() {
1101        use crate::crypto::Ed25519PrivateKey;
1102
1103        let private_key = Ed25519PrivateKey::generate();
1104        let sig0 = AnySignature::ed25519(&private_key.sign(b"test"));
1105        let sig2 = AnySignature::ed25519(&private_key.sign(b"test"));
1106
1107        let multi_sig = MultiKeySignature::new(vec![(0, sig0), (2, sig2)]).unwrap();
1108
1109        assert_eq!(multi_sig.num_signatures(), 2);
1110        assert_eq!(multi_sig.signatures().len(), 2);
1111    }
1112
1113    #[test]
1114    #[cfg(feature = "ed25519")]
1115    fn test_multi_key_public_key_debug() {
1116        use crate::crypto::Ed25519PrivateKey;
1117
1118        let keys: Vec<_> = (0..2)
1119            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1120            .collect();
1121        let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1122
1123        let debug = format!("{multi_pk:?}");
1124        assert!(debug.contains("MultiKeyPublicKey"));
1125    }
1126
1127    #[test]
1128    #[cfg(feature = "ed25519")]
1129    fn test_multi_key_signature_debug() {
1130        use crate::crypto::Ed25519PrivateKey;
1131
1132        let private_key = Ed25519PrivateKey::generate();
1133        let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1134        let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
1135
1136        let debug = format!("{multi_sig:?}");
1137        assert!(debug.contains("MultiKeySignature"));
1138    }
1139
1140    #[test]
1141    #[cfg(feature = "ed25519")]
1142    fn test_multi_key_public_key_display() {
1143        use crate::crypto::Ed25519PrivateKey;
1144
1145        let keys: Vec<_> = (0..2)
1146            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1147            .collect();
1148        let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1149
1150        let display = format!("{multi_pk}");
1151        assert!(display.starts_with("0x"));
1152    }
1153
1154    #[test]
1155    #[cfg(feature = "ed25519")]
1156    fn test_multi_key_signature_display() {
1157        use crate::crypto::Ed25519PrivateKey;
1158
1159        let private_key = Ed25519PrivateKey::generate();
1160        let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1161        let multi_sig = MultiKeySignature::new(vec![(0, sig)]).unwrap();
1162
1163        let display = format!("{multi_sig}");
1164        assert!(display.starts_with("0x"));
1165    }
1166
1167    #[test]
1168    #[cfg(feature = "ed25519")]
1169    fn test_multi_key_public_key_to_address() {
1170        use crate::crypto::Ed25519PrivateKey;
1171
1172        let keys: Vec<_> = (0..2)
1173            .map(|_| AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key()))
1174            .collect();
1175        let multi_pk = MultiKeyPublicKey::new(keys, 2).unwrap();
1176
1177        let address = multi_pk.to_address();
1178        assert!(!address.is_zero());
1179    }
1180
1181    #[test]
1182    fn test_any_public_key_variant_debug() {
1183        let variant = AnyPublicKeyVariant::Ed25519;
1184        let debug = format!("{variant:?}");
1185        assert!(debug.contains("Ed25519"));
1186    }
1187
1188    #[test]
1189    #[cfg(feature = "ed25519")]
1190    fn test_any_public_key_ed25519_debug() {
1191        use crate::crypto::Ed25519PrivateKey;
1192
1193        let pk = AnyPublicKey::ed25519(&Ed25519PrivateKey::generate().public_key());
1194        let debug = format!("{pk:?}");
1195        assert!(debug.contains("Ed25519"));
1196    }
1197
1198    #[test]
1199    #[cfg(feature = "ed25519")]
1200    fn test_any_signature_ed25519_debug() {
1201        use crate::crypto::Ed25519PrivateKey;
1202
1203        let private_key = Ed25519PrivateKey::generate();
1204        let sig = AnySignature::ed25519(&private_key.sign(b"test"));
1205        let debug = format!("{sig:?}");
1206        assert!(debug.contains("Ed25519"));
1207    }
1208
1209    #[test]
1210    #[cfg(feature = "ed25519")]
1211    fn test_multi_key_insufficient_signatures() {
1212        use crate::crypto::Ed25519PrivateKey;
1213
1214        let private_keys: Vec<_> = (0..3).map(|_| Ed25519PrivateKey::generate()).collect();
1215        let public_keys: Vec<_> = private_keys
1216            .iter()
1217            .map(|k| AnyPublicKey::ed25519(&k.public_key()))
1218            .collect();
1219
1220        let multi_pk = MultiKeyPublicKey::new(public_keys, 2).unwrap();
1221        let message = b"test message";
1222
1223        // Only provide 1 signature when threshold is 2
1224        let sig0 = AnySignature::ed25519(&private_keys[0].sign(message));
1225        let multi_sig = MultiKeySignature::new(vec![(0, sig0)]).unwrap();
1226
1227        // Verify should fail
1228        let result = multi_pk.verify(message, &multi_sig);
1229        assert!(result.is_err());
1230    }
1231}