Skip to main content

sui_types/
crypto.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3use crate::base_types::{AuthorityName, ConciseableName, SuiAddress};
4use crate::committee::CommitteeTrait;
5use crate::committee::{Committee, EpochId, StakeUnit};
6use crate::error::{SuiError, SuiErrorKind, SuiResult};
7use crate::signature::GenericSignature;
8use crate::sui_serde::{Readable, SuiBitmap};
9use anyhow::{Error, anyhow};
10use derive_more::{AsMut, AsRef, From};
11pub use enum_dispatch::enum_dispatch;
12use eyre::eyre;
13use fastcrypto::bls12381::min_sig::{
14    BLS12381AggregateSignature, BLS12381AggregateSignatureAsBytes, BLS12381KeyPair,
15    BLS12381PrivateKey, BLS12381PublicKey, BLS12381Signature,
16};
17use fastcrypto::ed25519::{
18    Ed25519KeyPair, Ed25519PrivateKey, Ed25519PublicKey, Ed25519PublicKeyAsBytes, Ed25519Signature,
19    Ed25519SignatureAsBytes,
20};
21use fastcrypto::encoding::{Base64, Bech32, Encoding, Hex};
22use fastcrypto::error::{FastCryptoError, FastCryptoResult};
23use fastcrypto::hash::{Blake2b256, HashFunction};
24use fastcrypto::secp256k1::{
25    Secp256k1KeyPair, Secp256k1PublicKey, Secp256k1PublicKeyAsBytes, Secp256k1Signature,
26    Secp256k1SignatureAsBytes,
27};
28use fastcrypto::secp256r1::{
29    Secp256r1KeyPair, Secp256r1PublicKey, Secp256r1PublicKeyAsBytes, Secp256r1Signature,
30    Secp256r1SignatureAsBytes,
31};
32pub use fastcrypto::traits::KeyPair as KeypairTraits;
33pub use fastcrypto::traits::Signer;
34pub use fastcrypto::traits::{
35    AggregateAuthenticator, Authenticator, EncodeDecodeBase64, SigningKey, ToFromBytes,
36    VerifyingKey,
37};
38use fastcrypto_pq::mldsa65::{
39    MLDSA65KeyPair, MLDSA65PublicKey, MLDSA65PublicKeyAsBytes, MLDSA65Signature,
40    MLDSA65SignatureAsBytes,
41};
42use fastcrypto_zkp::bn254::zk_login::ZkLoginInputs;
43use fastcrypto_zkp::zk_login_utils::Bn254FrElement;
44use rand::SeedableRng;
45use rand::rngs::{OsRng, StdRng};
46use roaring::RoaringBitmap;
47use schemars::JsonSchema;
48use serde::ser::Serializer;
49use serde::{Deserialize, Deserializer, Serialize};
50use serde_with::{Bytes, DeserializeAs, serde_as};
51use shared_crypto::intent::{Intent, IntentMessage, IntentScope};
52use std::collections::BTreeMap;
53use std::fmt::Debug;
54use std::fmt::{self, Display, Formatter};
55use std::hash::{Hash, Hasher};
56use std::str::FromStr;
57use strum::EnumString;
58use tracing::{instrument, warn};
59
60#[cfg(test)]
61#[path = "unit_tests/crypto_tests.rs"]
62mod crypto_tests;
63
64#[cfg(test)]
65#[path = "unit_tests/intent_tests.rs"]
66mod intent_tests;
67
68// Authority Objects
69pub type AuthorityKeyPair = BLS12381KeyPair;
70pub type AuthorityPublicKey = BLS12381PublicKey;
71pub type AuthorityPrivateKey = BLS12381PrivateKey;
72pub type AuthoritySignature = BLS12381Signature;
73pub type AggregateAuthoritySignature = BLS12381AggregateSignature;
74pub type AggregateAuthoritySignatureAsBytes = BLS12381AggregateSignatureAsBytes;
75
76// TODO(joyqvq): prefix these types with Default, DefaultAccountKeyPair etc
77pub type AccountKeyPair = Ed25519KeyPair;
78pub type AccountPublicKey = Ed25519PublicKey;
79pub type AccountPrivateKey = Ed25519PrivateKey;
80
81pub type NetworkKeyPair = Ed25519KeyPair;
82pub type NetworkPublicKey = Ed25519PublicKey;
83pub type NetworkPrivateKey = Ed25519PrivateKey;
84
85pub type DefaultHash = Blake2b256;
86
87pub const DEFAULT_EPOCH_ID: EpochId = 0;
88pub const SUI_PRIV_KEY_PREFIX: &str = "suiprivkey";
89
90/// Creates a proof of that the authority account address is owned by the
91/// holder of authority protocol key, and also ensures that the authority
92/// protocol public key exists. A proof of possession is an authority
93/// signature committed over the intent message `intent || message || epoch` (See
94/// more at [struct IntentMessage] and [struct Intent]) where the message is
95/// constructed as `authority_pubkey_bytes || authority_account_address`.
96pub fn generate_proof_of_possession(
97    keypair: &AuthorityKeyPair,
98    address: SuiAddress,
99) -> AuthoritySignature {
100    let mut msg: Vec<u8> = Vec::new();
101    msg.extend_from_slice(keypair.public().as_bytes());
102    msg.extend_from_slice(address.as_ref());
103    AuthoritySignature::new_secure(
104        &IntentMessage::new(Intent::sui_app(IntentScope::ProofOfPossession), msg),
105        &DEFAULT_EPOCH_ID,
106        keypair,
107    )
108}
109
110/// Verify proof of possession against the expected intent message,
111/// consisting of the protocol pubkey and the authority account address.
112pub fn verify_proof_of_possession(
113    pop: &AuthoritySignature,
114    protocol_pubkey: &AuthorityPublicKey,
115    sui_address: SuiAddress,
116) -> Result<(), SuiError> {
117    protocol_pubkey
118        .validate()
119        .map_err(|_| SuiErrorKind::InvalidSignature {
120            error: "Fail to validate pubkey".to_string(),
121        })?;
122    let mut msg = protocol_pubkey.as_bytes().to_vec();
123    msg.extend_from_slice(sui_address.as_ref());
124    pop.verify_secure(
125        &IntentMessage::new(Intent::sui_app(IntentScope::ProofOfPossession), msg),
126        DEFAULT_EPOCH_ID,
127        protocol_pubkey.into(),
128    )
129}
130///////////////////////////////////////////////
131// Account Keys
132//
133// * The following section defines the keypairs that are used by
134// * accounts to interact with Sui.
135// * Currently we support eddsa, ecdsa and ML-DSA-65 on Sui.
136//
137
138#[allow(clippy::large_enum_variant)]
139#[derive(Debug, From, PartialEq, Eq)]
140pub enum SuiKeyPair {
141    Ed25519(Ed25519KeyPair),
142    Secp256k1(Secp256k1KeyPair),
143    Secp256r1(Secp256r1KeyPair),
144    MLDSA65(MLDSA65KeyPair),
145}
146
147impl SuiKeyPair {
148    pub fn public(&self) -> PublicKey {
149        match self {
150            SuiKeyPair::Ed25519(kp) => PublicKey::Ed25519(kp.public().into()),
151            SuiKeyPair::Secp256k1(kp) => PublicKey::Secp256k1(kp.public().into()),
152            SuiKeyPair::Secp256r1(kp) => PublicKey::Secp256r1(kp.public().into()),
153            SuiKeyPair::MLDSA65(kp) => PublicKey::MLDSA65(Box::new(kp.public().into())),
154        }
155    }
156
157    pub fn copy(&self) -> Self {
158        match self {
159            SuiKeyPair::Ed25519(kp) => kp.copy().into(),
160            SuiKeyPair::Secp256k1(kp) => kp.copy().into(),
161            SuiKeyPair::Secp256r1(kp) => kp.copy().into(),
162            SuiKeyPair::MLDSA65(kp) => kp.copy().into(),
163        }
164    }
165}
166
167impl Signer<Signature> for SuiKeyPair {
168    fn sign(&self, msg: &[u8]) -> Signature {
169        match self {
170            SuiKeyPair::Ed25519(kp) => kp.sign(msg),
171            SuiKeyPair::Secp256k1(kp) => kp.sign(msg),
172            SuiKeyPair::Secp256r1(kp) => kp.sign(msg),
173            SuiKeyPair::MLDSA65(kp) => kp.sign(msg),
174        }
175    }
176}
177
178impl EncodeDecodeBase64 for SuiKeyPair {
179    fn encode_base64(&self) -> String {
180        Base64::encode(self.to_bytes())
181    }
182
183    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
184        let bytes = Base64::decode(value)?;
185        Self::from_bytes(&bytes).map_err(|_| FastCryptoError::InvalidInput)
186    }
187}
188impl SuiKeyPair {
189    pub fn to_bytes(&self) -> Vec<u8> {
190        let mut bytes: Vec<u8> = Vec::new();
191        bytes.push(self.public().flag());
192
193        match self {
194            SuiKeyPair::Ed25519(kp) => {
195                bytes.extend_from_slice(kp.as_bytes());
196            }
197            SuiKeyPair::Secp256k1(kp) => {
198                bytes.extend_from_slice(kp.as_bytes());
199            }
200            SuiKeyPair::Secp256r1(kp) => {
201                bytes.extend_from_slice(kp.as_bytes());
202            }
203            // as_bytes is the 32-byte FIPS 204 seed, so the blob keeps the flag || privkey shape.
204            SuiKeyPair::MLDSA65(kp) => {
205                bytes.extend_from_slice(kp.as_bytes());
206            }
207        }
208        bytes
209    }
210
211    pub fn from_bytes(bytes: &[u8]) -> Result<Self, eyre::Report> {
212        match SignatureScheme::from_flag_byte(bytes.first().ok_or_else(|| eyre!("Invalid length"))?)
213        {
214            Ok(x) => match x {
215                SignatureScheme::ED25519 => Ok(SuiKeyPair::Ed25519(Ed25519KeyPair::from_bytes(
216                    bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
217                )?)),
218                SignatureScheme::Secp256k1 => {
219                    Ok(SuiKeyPair::Secp256k1(Secp256k1KeyPair::from_bytes(
220                        bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
221                    )?))
222                }
223                SignatureScheme::Secp256r1 => {
224                    Ok(SuiKeyPair::Secp256r1(Secp256r1KeyPair::from_bytes(
225                        bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
226                    )?))
227                }
228                // Only the 32-byte seed is accepted; the expanded key is re-derived from it.
229                SignatureScheme::MLDSA65 => Ok(SuiKeyPair::MLDSA65(MLDSA65KeyPair::from_bytes(
230                    bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
231                )?)),
232                _ => Err(eyre!("Invalid flag byte")),
233            },
234            _ => Err(eyre!("Invalid bytes")),
235        }
236    }
237
238    pub fn to_bytes_no_flag(&self) -> Vec<u8> {
239        match self {
240            SuiKeyPair::Ed25519(kp) => kp.as_bytes().to_vec(),
241            SuiKeyPair::Secp256k1(kp) => kp.as_bytes().to_vec(),
242            SuiKeyPair::Secp256r1(kp) => kp.as_bytes().to_vec(),
243            SuiKeyPair::MLDSA65(kp) => kp.as_bytes().to_vec(),
244        }
245    }
246
247    /// Encode a SuiKeyPair as `flag || privkey` in Bech32 starting with "suiprivkey" to a string. Note that the pubkey is not encoded.
248    pub fn encode(&self) -> Result<String, eyre::Report> {
249        Bech32::encode(self.to_bytes(), SUI_PRIV_KEY_PREFIX).map_err(|e| eyre!(e))
250    }
251
252    /// Decode a SuiKeyPair from `flag || privkey` in Bech32 starting with "suiprivkey" to SuiKeyPair. The public key is computed directly from the private key bytes.
253    pub fn decode(value: &str) -> Result<Self, eyre::Report> {
254        let bytes = Bech32::decode(value, SUI_PRIV_KEY_PREFIX)?;
255        Self::from_bytes(&bytes)
256    }
257}
258
259impl Serialize for SuiKeyPair {
260    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
261    where
262        S: Serializer,
263    {
264        let s = self.encode_base64();
265        serializer.serialize_str(&s)
266    }
267}
268
269impl<'de> Deserialize<'de> for SuiKeyPair {
270    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
271    where
272        D: Deserializer<'de>,
273    {
274        use serde::de::Error;
275        let s = String::deserialize(deserializer)?;
276        SuiKeyPair::decode_base64(&s).map_err(|e| Error::custom(e.to_string()))
277    }
278}
279
280#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, Serialize, Deserialize)]
281pub enum PublicKey {
282    Ed25519(Ed25519PublicKeyAsBytes),
283    Secp256k1(Secp256k1PublicKeyAsBytes),
284    Secp256r1(Secp256r1PublicKeyAsBytes),
285    ZkLogin(ZkLoginPublicIdentifier),
286    Passkey(Secp256r1PublicKeyAsBytes),
287    // Boxed because the 1,952-byte pk; Box is transparent to BCS.
288    // Schema-only skip (serde unaffected): keeps the generated openrpc spec
289    // unchanged, since deprecated JSON-RPC will never serve ML-DSA.
290    #[schemars(skip)]
291    MLDSA65(Box<MLDSA65PublicKeyAsBytes>),
292}
293
294/// A wrapper struct to retrofit in [enum PublicKey] for zkLogin.
295/// Useful to construct [struct MultiSigPublicKey].
296#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, Serialize, Deserialize)]
297pub struct ZkLoginPublicIdentifier(#[schemars(with = "Base64")] pub Vec<u8>);
298
299impl ZkLoginPublicIdentifier {
300    /// Consists of iss_bytes_len || iss_bytes || padded_32_byte_address_seed.
301    pub fn new(iss: &str, address_seed: &Bn254FrElement) -> SuiResult<Self> {
302        let mut bytes = Vec::new();
303        let iss_bytes = iss.as_bytes();
304        bytes.extend([iss_bytes.len() as u8]);
305        bytes.extend(iss_bytes);
306        bytes.extend(address_seed.padded());
307
308        Ok(Self(bytes))
309    }
310
311    /// Validates zkLogin public identifier structure: iss_len || iss || padded_32_byte_address_seed.
312    pub fn validate(&self) -> SuiResult<()> {
313        let bytes = &self.0;
314
315        // Parse issuer length and bytes.
316        let iss_len = *bytes
317            .first()
318            .ok_or_else(|| SuiErrorKind::InvalidSignature {
319                error: "invalid zklogin pk".to_string(),
320            })? as usize;
321        let iss_bytes =
322            bytes
323                .get(1..1 + iss_len)
324                .ok_or_else(|| SuiErrorKind::InvalidSignature {
325                    error: "invalid zklogin pk iss length".to_string(),
326                })?;
327
328        // Validate issuer string.
329        std::str::from_utf8(iss_bytes).map_err(|e| SuiErrorKind::InvalidSignature {
330            error: format!("zkLogin pk issuer is not valid: {}", e),
331        })?;
332
333        // Validate address seed length <= 32 bytes.
334        let address_seed_bytes =
335            bytes
336                .get(1 + iss_len..)
337                .ok_or_else(|| SuiErrorKind::InvalidSignature {
338                    error: "zkLogin pk has no address seed".to_string(),
339                })?;
340
341        if address_seed_bytes.len() > 32 {
342            return Err(SuiErrorKind::InvalidSignature {
343                error: format!(
344                    "address seed must be at most 32 bytes, got {}",
345                    address_seed_bytes.len()
346                ),
347            }
348            .into());
349        }
350
351        Ok(())
352    }
353}
354impl AsRef<[u8]> for PublicKey {
355    fn as_ref(&self) -> &[u8] {
356        match self {
357            PublicKey::Ed25519(pk) => &pk.0,
358            PublicKey::Secp256k1(pk) => &pk.0,
359            PublicKey::Secp256r1(pk) => &pk.0,
360            PublicKey::ZkLogin(z) => &z.0,
361            PublicKey::Passkey(pk) => &pk.0,
362            PublicKey::MLDSA65(pk) => &pk.0,
363        }
364    }
365}
366
367impl EncodeDecodeBase64 for PublicKey {
368    fn encode_base64(&self) -> String {
369        let mut bytes: Vec<u8> = Vec::new();
370        bytes.extend_from_slice(&[self.flag()]);
371        bytes.extend_from_slice(self.as_ref());
372        Base64::encode(&bytes[..])
373    }
374
375    fn decode_base64(value: &str) -> FastCryptoResult<Self> {
376        let bytes = Base64::decode(value)?;
377        match bytes.first() {
378            Some(x) => {
379                if x == &SignatureScheme::ED25519.flag() {
380                    let pk: Ed25519PublicKey =
381                        Ed25519PublicKey::from_bytes(bytes.get(1..).ok_or(
382                            FastCryptoError::InputLengthWrong(Ed25519PublicKey::LENGTH + 1),
383                        )?)?;
384                    Ok(PublicKey::Ed25519((&pk).into()))
385                } else if x == &SignatureScheme::Secp256k1.flag() {
386                    let pk = Secp256k1PublicKey::from_bytes(bytes.get(1..).ok_or(
387                        FastCryptoError::InputLengthWrong(Secp256k1PublicKey::LENGTH + 1),
388                    )?)?;
389                    Ok(PublicKey::Secp256k1((&pk).into()))
390                } else if x == &SignatureScheme::Secp256r1.flag() {
391                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
392                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
393                    )?)?;
394                    Ok(PublicKey::Secp256r1((&pk).into()))
395                } else if x == &SignatureScheme::PasskeyAuthenticator.flag() {
396                    let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
397                        FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
398                    )?)?;
399                    Ok(PublicKey::Passkey((&pk).into()))
400                } else if x == &SignatureScheme::MLDSA65.flag() {
401                    let pk = MLDSA65PublicKey::from_bytes(bytes.get(1..).ok_or(
402                        FastCryptoError::InputLengthWrong(MLDSA65PublicKey::LENGTH + 1),
403                    )?)?;
404                    Ok(PublicKey::MLDSA65(Box::new((&pk).into())))
405                } else {
406                    Err(FastCryptoError::InvalidInput)
407                }
408            }
409            _ => Err(FastCryptoError::InvalidInput),
410        }
411    }
412}
413
414impl PublicKey {
415    pub fn flag(&self) -> u8 {
416        self.scheme().flag()
417    }
418
419    pub fn try_from_bytes(
420        curve: SignatureScheme,
421        key_bytes: &[u8],
422    ) -> Result<PublicKey, eyre::Report> {
423        match curve {
424            SignatureScheme::ED25519 => Ok(PublicKey::Ed25519(
425                (&Ed25519PublicKey::from_bytes(key_bytes)?).into(),
426            )),
427            SignatureScheme::Secp256k1 => Ok(PublicKey::Secp256k1(
428                (&Secp256k1PublicKey::from_bytes(key_bytes)?).into(),
429            )),
430            SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
431                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
432            )),
433            SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
434                (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
435            )),
436            SignatureScheme::MLDSA65 => Ok(PublicKey::MLDSA65(Box::new(
437                (&MLDSA65PublicKey::from_bytes(key_bytes)?).into(),
438            ))),
439            _ => Err(eyre!("Unsupported curve")),
440        }
441    }
442
443    pub fn scheme(&self) -> SignatureScheme {
444        match self {
445            PublicKey::Ed25519(_) => Ed25519SuiSignature::SCHEME,
446            PublicKey::Secp256k1(_) => Secp256k1SuiSignature::SCHEME,
447            PublicKey::Secp256r1(_) => Secp256r1SuiSignature::SCHEME,
448            PublicKey::ZkLogin(_) => SignatureScheme::ZkLoginAuthenticator,
449            PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
450            PublicKey::MLDSA65(_) => MLDSA65SuiSignature::SCHEME,
451        }
452    }
453
454    pub fn from_zklogin_inputs(inputs: &ZkLoginInputs) -> SuiResult<Self> {
455        Ok(PublicKey::ZkLogin(ZkLoginPublicIdentifier::new(
456            inputs.get_iss(),
457            inputs.get_address_seed(),
458        )?))
459    }
460}
461
462/// Defines the compressed version of the public key that we pass around
463/// in Sui
464#[serde_as]
465#[derive(
466    Copy,
467    Clone,
468    PartialEq,
469    Eq,
470    Hash,
471    PartialOrd,
472    Ord,
473    Serialize,
474    Deserialize,
475    schemars::JsonSchema,
476    AsRef,
477)]
478#[as_ref(forward)]
479pub struct AuthorityPublicKeyBytes(
480    #[schemars(with = "Base64")]
481    #[serde_as(as = "Readable<Base64, Bytes>")]
482    pub [u8; AuthorityPublicKey::LENGTH],
483);
484
485impl AuthorityPublicKeyBytes {
486    fn fmt_impl(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
487        let s = Hex::encode(self.0);
488        write!(f, "k#{}", s)?;
489        Ok(())
490    }
491}
492
493impl<'a> ConciseableName<'a> for AuthorityPublicKeyBytes {
494    type ConciseTypeRef = ConciseAuthorityPublicKeyBytesRef<'a>;
495    type ConciseType = ConciseAuthorityPublicKeyBytes;
496
497    /// Get a ConciseAuthorityPublicKeyBytesRef. Usage:
498    ///
499    ///   debug!(name = ?authority.concise());
500    ///   format!("{:?}", authority.concise());
501    fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
502        ConciseAuthorityPublicKeyBytesRef(self)
503    }
504
505    fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
506        ConciseAuthorityPublicKeyBytes(*self)
507    }
508}
509
510/// A wrapper around AuthorityPublicKeyBytes that provides a concise Debug impl.
511pub struct ConciseAuthorityPublicKeyBytesRef<'a>(&'a AuthorityPublicKeyBytes);
512
513impl Debug for ConciseAuthorityPublicKeyBytesRef<'_> {
514    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
515        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
516        write!(f, "k#{}..", s)
517    }
518}
519
520impl Display for ConciseAuthorityPublicKeyBytesRef<'_> {
521    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
522        Debug::fmt(self, f)
523    }
524}
525
526/// A wrapper around AuthorityPublicKeyBytes but owns it.
527#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, schemars::JsonSchema)]
528pub struct ConciseAuthorityPublicKeyBytes(AuthorityPublicKeyBytes);
529
530impl Debug for ConciseAuthorityPublicKeyBytes {
531    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
532        let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
533        write!(f, "k#{}..", s)
534    }
535}
536
537impl Display for ConciseAuthorityPublicKeyBytes {
538    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
539        Debug::fmt(self, f)
540    }
541}
542
543impl TryFrom<AuthorityPublicKeyBytes> for AuthorityPublicKey {
544    type Error = FastCryptoError;
545
546    fn try_from(bytes: AuthorityPublicKeyBytes) -> Result<AuthorityPublicKey, Self::Error> {
547        AuthorityPublicKey::from_bytes(bytes.as_ref())
548    }
549}
550
551impl From<&AuthorityPublicKey> for AuthorityPublicKeyBytes {
552    fn from(pk: &AuthorityPublicKey) -> AuthorityPublicKeyBytes {
553        AuthorityPublicKeyBytes::from_bytes(pk.as_ref()).unwrap()
554    }
555}
556
557impl Debug for AuthorityPublicKeyBytes {
558    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
559        self.fmt_impl(f)
560    }
561}
562
563impl Display for AuthorityPublicKeyBytes {
564    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
565        self.fmt_impl(f)
566    }
567}
568
569impl ToFromBytes for AuthorityPublicKeyBytes {
570    fn from_bytes(bytes: &[u8]) -> Result<Self, fastcrypto::error::FastCryptoError> {
571        let bytes: [u8; AuthorityPublicKey::LENGTH] = bytes
572            .try_into()
573            .map_err(|_| fastcrypto::error::FastCryptoError::InvalidInput)?;
574        Ok(AuthorityPublicKeyBytes(bytes))
575    }
576}
577
578impl AuthorityPublicKeyBytes {
579    pub const ZERO: Self = Self::new([0u8; AuthorityPublicKey::LENGTH]);
580
581    /// This ensures it's impossible to construct an instance with other than registered lengths
582    pub const fn new(bytes: [u8; AuthorityPublicKey::LENGTH]) -> AuthorityPublicKeyBytes
583where {
584        AuthorityPublicKeyBytes(bytes)
585    }
586}
587
588impl FromStr for AuthorityPublicKeyBytes {
589    type Err = Error;
590
591    fn from_str(s: &str) -> Result<Self, Self::Err> {
592        let value = Hex::decode(s).map_err(|e| anyhow!(e))?;
593        Self::from_bytes(&value[..]).map_err(|e| anyhow!(e))
594    }
595}
596
597impl Default for AuthorityPublicKeyBytes {
598    fn default() -> Self {
599        Self::ZERO
600    }
601}
602
603//
604// Add helper calls for Authority Signature
605//
606
607pub trait SuiAuthoritySignature {
608    fn verify_secure<T>(
609        &self,
610        value: &IntentMessage<T>,
611        epoch_id: EpochId,
612        author: AuthorityPublicKeyBytes,
613    ) -> Result<(), SuiError>
614    where
615        T: Serialize;
616
617    fn new_secure<T>(
618        value: &IntentMessage<T>,
619        epoch_id: &EpochId,
620        secret: &dyn Signer<Self>,
621    ) -> Self
622    where
623        T: Serialize;
624}
625
626impl SuiAuthoritySignature for AuthoritySignature {
627    #[instrument(level = "trace", skip_all)]
628    fn new_secure<T>(value: &IntentMessage<T>, epoch: &EpochId, secret: &dyn Signer<Self>) -> Self
629    where
630        T: Serialize,
631    {
632        let mut intent_msg_bytes =
633            bcs::to_bytes(&value).expect("Message serialization should not fail");
634        epoch.write(&mut intent_msg_bytes);
635        secret.sign(&intent_msg_bytes)
636    }
637
638    #[instrument(level = "trace", skip_all)]
639    fn verify_secure<T>(
640        &self,
641        value: &IntentMessage<T>,
642        epoch: EpochId,
643        author: AuthorityPublicKeyBytes,
644    ) -> Result<(), SuiError>
645    where
646        T: Serialize,
647    {
648        let mut message = bcs::to_bytes(&value).expect("Message serialization should not fail");
649        epoch.write(&mut message);
650
651        let public_key = AuthorityPublicKey::try_from(author).map_err(|_| {
652            SuiErrorKind::KeyConversionError(
653                "Failed to serialize public key bytes to valid public key".to_string(),
654            )
655        })?;
656        public_key.verify(&message[..], self).map_err(|e| {
657            SuiErrorKind::InvalidSignature {
658                error: format!(
659                    "Fail to verify auth sig {} epoch: {} author: {}",
660                    e,
661                    epoch,
662                    author.concise()
663                ),
664            }
665            .into()
666        })
667    }
668}
669
670// TODO: get_key_pair() and get_key_pair_from_bytes() should return KeyPair only.
671// TODO: rename to random_key_pair
672pub fn get_key_pair<KP: KeypairTraits>() -> (SuiAddress, KP)
673where
674    <KP as KeypairTraits>::PubKey: SuiPublicKey,
675{
676    get_key_pair_from_rng(&mut OsRng)
677}
678
679/// Generate a random committee key pairs with a given committee size
680pub fn random_committee_key_pairs_of_size(size: usize) -> Vec<AuthorityKeyPair> {
681    let mut rng = StdRng::from_seed([0; 32]);
682    (0..size)
683        .map(|_| {
684            // TODO: We are generating the keys 4 times to match exactly as how we generate
685            // keys in ConfigBuilder::build (sui-config/src/network_config_builder). This is because
686            // we are using these key generation functions as fixtures and we call them
687            // independently in different paths and exact the results to be the same.
688            // We should eliminate them.
689            let key_pair = get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
690            get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
691            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
692            get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
693            key_pair.1
694        })
695        .collect()
696}
697
698pub fn deterministic_random_account_key() -> (SuiAddress, AccountKeyPair) {
699    let mut rng = StdRng::from_seed([0; 32]);
700    get_key_pair_from_rng(&mut rng)
701}
702
703pub fn get_account_key_pair() -> (SuiAddress, AccountKeyPair) {
704    get_key_pair()
705}
706
707pub fn get_authority_key_pair() -> (SuiAddress, AuthorityKeyPair) {
708    get_key_pair()
709}
710
711/// Generate a keypair from the specified RNG (useful for testing with seedable rngs).
712pub fn get_key_pair_from_rng<KP: KeypairTraits, R>(csprng: &mut R) -> (SuiAddress, KP)
713where
714    R: rand::CryptoRng + rand::RngCore,
715    <KP as KeypairTraits>::PubKey: SuiPublicKey,
716{
717    let kp = KP::generate(&mut StdRng::from_rng(csprng).unwrap());
718    (kp.public().into(), kp)
719}
720
721// TODO: C-GETTER
722pub fn get_key_pair_from_bytes<KP: KeypairTraits>(bytes: &[u8]) -> SuiResult<(SuiAddress, KP)>
723where
724    <KP as KeypairTraits>::PubKey: SuiPublicKey,
725{
726    let priv_length = <KP as KeypairTraits>::PrivKey::LENGTH;
727    let pub_key_length = <KP as KeypairTraits>::PubKey::LENGTH;
728    if bytes.len() != priv_length + pub_key_length {
729        return Err(SuiErrorKind::KeyConversionError(format!(
730            "Invalid input byte length, expected {}: {}",
731            priv_length,
732            bytes.len()
733        ))
734        .into());
735    }
736    let sk = <KP as KeypairTraits>::PrivKey::from_bytes(
737        bytes
738            .get(..priv_length)
739            .ok_or(SuiErrorKind::InvalidPrivateKey)?,
740    )
741    .map_err(|_| SuiErrorKind::InvalidPrivateKey)?;
742    let kp: KP = sk.into();
743    Ok((kp.public().into(), kp))
744}
745
746//
747// Account Signatures
748//
749
750// Enums for signature scheme signatures
751#[enum_dispatch]
752#[derive(Clone, JsonSchema, Debug, PartialEq, Eq, Hash)]
753pub enum Signature {
754    Ed25519SuiSignature,
755    Secp256k1SuiSignature,
756    Secp256r1SuiSignature,
757    // Schema-only skip: see `PublicKey::MLDSA65`.
758    #[schemars(skip)]
759    MLDSA65SuiSignature,
760}
761
762impl Serialize for Signature {
763    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
764    where
765        S: Serializer,
766    {
767        let bytes = self.as_ref();
768
769        if serializer.is_human_readable() {
770            let s = Base64::encode(bytes);
771            serializer.serialize_str(&s)
772        } else {
773            serializer.serialize_bytes(bytes)
774        }
775    }
776}
777
778impl<'de> Deserialize<'de> for Signature {
779    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
780    where
781        D: Deserializer<'de>,
782    {
783        use serde::de::Error;
784
785        let bytes = if deserializer.is_human_readable() {
786            let s = String::deserialize(deserializer)?;
787            Base64::decode(&s).map_err(|e| Error::custom(e.to_string()))?
788        } else {
789            Bytes::deserialize_as(deserializer)?
790        };
791
792        Self::from_bytes(&bytes).map_err(|e| Error::custom(e.to_string()))
793    }
794}
795
796impl Signature {
797    /// The messaged passed in is already hashed form.
798    pub fn new_hashed(hashed_msg: &[u8], secret: &dyn Signer<Signature>) -> Self {
799        Signer::sign(secret, hashed_msg)
800    }
801
802    pub fn new_secure<T>(value: &IntentMessage<T>, secret: &dyn Signer<Signature>) -> Self
803    where
804        T: Serialize,
805    {
806        // Compute the BCS hash of the value in intent message. In the case of transaction data,
807        // this is the BCS hash of `struct TransactionData`, different from the transaction digest
808        // itself that computes the BCS hash of the Rust type prefix and `struct TransactionData`.
809        // (See `fn digest` in `impl Message for SenderSignedData`).
810        let mut hasher = DefaultHash::default();
811        bcs::serialize_into(&mut hasher, &value).expect("Message serialization should not fail");
812
813        Signer::sign(secret, &hasher.finalize().digest)
814    }
815}
816
817impl AsRef<[u8]> for Signature {
818    fn as_ref(&self) -> &[u8] {
819        match self {
820            Signature::Ed25519SuiSignature(sig) => sig.as_ref(),
821            Signature::Secp256k1SuiSignature(sig) => sig.as_ref(),
822            Signature::Secp256r1SuiSignature(sig) => sig.as_ref(),
823            Signature::MLDSA65SuiSignature(sig) => sig.as_ref(),
824        }
825    }
826}
827impl AsMut<[u8]> for Signature {
828    fn as_mut(&mut self) -> &mut [u8] {
829        match self {
830            Signature::Ed25519SuiSignature(sig) => sig.as_mut(),
831            Signature::Secp256k1SuiSignature(sig) => sig.as_mut(),
832            Signature::Secp256r1SuiSignature(sig) => sig.as_mut(),
833            Signature::MLDSA65SuiSignature(sig) => sig.as_mut(),
834        }
835    }
836}
837
838impl ToFromBytes for Signature {
839    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
840        match bytes.first() {
841            Some(x) => {
842                if x == &Ed25519SuiSignature::SCHEME.flag() {
843                    Ok(<Ed25519SuiSignature as ToFromBytes>::from_bytes(bytes)?.into())
844                } else if x == &Secp256k1SuiSignature::SCHEME.flag() {
845                    Ok(<Secp256k1SuiSignature as ToFromBytes>::from_bytes(bytes)?.into())
846                } else if x == &Secp256r1SuiSignature::SCHEME.flag() {
847                    Ok(<Secp256r1SuiSignature as ToFromBytes>::from_bytes(bytes)?.into())
848                } else if x == &MLDSA65SuiSignature::SCHEME.flag() {
849                    Ok(<MLDSA65SuiSignature as ToFromBytes>::from_bytes(bytes)?.into())
850                } else {
851                    Err(FastCryptoError::InvalidInput)
852                }
853            }
854            _ => Err(FastCryptoError::InvalidInput),
855        }
856    }
857}
858
859//
860// BLS Port
861//
862
863impl SuiPublicKey for BLS12381PublicKey {
864    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::BLS12381;
865}
866
867//
868// Ed25519 Sui Signature port
869//
870
871#[serde_as]
872#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
873#[as_ref(forward)]
874#[as_mut(forward)]
875pub struct Ed25519SuiSignature(
876    #[schemars(with = "Base64")]
877    #[serde_as(as = "Readable<Base64, Bytes>")]
878    [u8; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1],
879);
880
881// Implementation useful for simplify testing when mock signature is needed
882impl Default for Ed25519SuiSignature {
883    fn default() -> Self {
884        Self([0; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1])
885    }
886}
887
888impl SuiSignatureInner for Ed25519SuiSignature {
889    type Sig = Ed25519Signature;
890    type PubKey = Ed25519PublicKey;
891    type KeyPair = Ed25519KeyPair;
892    const LENGTH: usize = Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1;
893}
894
895impl SuiPublicKey for Ed25519PublicKey {
896    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::ED25519;
897}
898
899impl ToFromBytes for Ed25519SuiSignature {
900    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
901        if bytes.len() != Self::LENGTH {
902            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
903        }
904        let mut sig_bytes = [0; Self::LENGTH];
905        sig_bytes.copy_from_slice(bytes);
906        Ok(Self(sig_bytes))
907    }
908}
909
910impl Signer<Signature> for Ed25519KeyPair {
911    fn sign(&self, msg: &[u8]) -> Signature {
912        Ed25519SuiSignature::new(self, msg).into()
913    }
914}
915
916//
917// Secp256k1 Sui Signature port
918//
919#[serde_as]
920#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
921#[as_ref(forward)]
922#[as_mut(forward)]
923pub struct Secp256k1SuiSignature(
924    #[schemars(with = "Base64")]
925    #[serde_as(as = "Readable<Base64, Bytes>")]
926    [u8; Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1],
927);
928
929impl SuiSignatureInner for Secp256k1SuiSignature {
930    type Sig = Secp256k1Signature;
931    type PubKey = Secp256k1PublicKey;
932    type KeyPair = Secp256k1KeyPair;
933    const LENGTH: usize = Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1;
934}
935
936impl SuiPublicKey for Secp256k1PublicKey {
937    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256k1;
938}
939
940impl ToFromBytes for Secp256k1SuiSignature {
941    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
942        if bytes.len() != Self::LENGTH {
943            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
944        }
945        let mut sig_bytes = [0; Self::LENGTH];
946        sig_bytes.copy_from_slice(bytes);
947        Ok(Self(sig_bytes))
948    }
949}
950
951impl Signer<Signature> for Secp256k1KeyPair {
952    fn sign(&self, msg: &[u8]) -> Signature {
953        Secp256k1SuiSignature::new(self, msg).into()
954    }
955}
956
957//
958// Secp256r1 Sui Signature port
959//
960#[serde_as]
961#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
962#[as_ref(forward)]
963#[as_mut(forward)]
964pub struct Secp256r1SuiSignature(
965    #[schemars(with = "Base64")]
966    #[serde_as(as = "Readable<Base64, Bytes>")]
967    [u8; Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1],
968);
969
970impl SuiSignatureInner for Secp256r1SuiSignature {
971    type Sig = Secp256r1Signature;
972    type PubKey = Secp256r1PublicKey;
973    type KeyPair = Secp256r1KeyPair;
974    const LENGTH: usize = Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1;
975}
976
977impl SuiPublicKey for Secp256r1PublicKey {
978    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
979}
980
981impl ToFromBytes for Secp256r1SuiSignature {
982    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
983        if bytes.len() != Self::LENGTH {
984            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
985        }
986        let mut sig_bytes = [0; Self::LENGTH];
987        sig_bytes.copy_from_slice(bytes);
988        Ok(Self(sig_bytes))
989    }
990}
991
992impl Signer<Signature> for Secp256r1KeyPair {
993    fn sign(&self, msg: &[u8]) -> Signature {
994        Secp256r1SuiSignature::new(self, msg).into()
995    }
996}
997
998//
999// ML-DSA-65 Sui Signature port
1000//
1001// Boxed: the 5,262-byte envelope would otherwise dominate every enum carrying a `Signature`.
1002#[derive(Clone, Debug, JsonSchema, PartialEq, Eq, Hash)]
1003pub struct MLDSA65SuiSignature(
1004    #[schemars(with = "Base64")] Box<[u8; MLDSA65PublicKey::LENGTH + MLDSA65Signature::LENGTH + 1]>,
1005);
1006
1007impl AsRef<[u8]> for MLDSA65SuiSignature {
1008    fn as_ref(&self) -> &[u8] {
1009        &self.0[..]
1010    }
1011}
1012
1013impl AsMut<[u8]> for MLDSA65SuiSignature {
1014    fn as_mut(&mut self) -> &mut [u8] {
1015        &mut self.0[..]
1016    }
1017}
1018
1019impl Serialize for MLDSA65SuiSignature {
1020    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1021    where
1022        S: Serializer,
1023    {
1024        if serializer.is_human_readable() {
1025            serializer.serialize_str(&Base64::encode(self.as_ref()))
1026        } else {
1027            serializer.serialize_bytes(self.as_ref())
1028        }
1029    }
1030}
1031
1032impl<'de> Deserialize<'de> for MLDSA65SuiSignature {
1033    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1034    where
1035        D: Deserializer<'de>,
1036    {
1037        use serde::de::Error;
1038        let bytes = if deserializer.is_human_readable() {
1039            let s = String::deserialize(deserializer)?;
1040            Base64::decode(&s).map_err(|e| Error::custom(e.to_string()))?
1041        } else {
1042            Bytes::deserialize_as(deserializer)?
1043        };
1044        Self::from_bytes(&bytes).map_err(|e| Error::custom(e.to_string()))
1045    }
1046}
1047
1048impl SuiSignatureInner for MLDSA65SuiSignature {
1049    type Sig = MLDSA65Signature;
1050    type PubKey = MLDSA65PublicKey;
1051    type KeyPair = MLDSA65KeyPair;
1052    const LENGTH: usize = MLDSA65PublicKey::LENGTH + MLDSA65Signature::LENGTH + 1;
1053}
1054
1055impl SuiPublicKey for MLDSA65PublicKey {
1056    const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::MLDSA65;
1057}
1058
1059impl ToFromBytes for MLDSA65SuiSignature {
1060    fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
1061        if bytes.len() != Self::LENGTH {
1062            return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
1063        }
1064        let mut sig_bytes = Box::new([0; Self::LENGTH]);
1065        sig_bytes.copy_from_slice(bytes);
1066        Ok(Self(sig_bytes))
1067    }
1068}
1069
1070impl Signer<Signature> for MLDSA65KeyPair {
1071    fn sign(&self, msg: &[u8]) -> Signature {
1072        MLDSA65SuiSignature::new(self, msg).into()
1073    }
1074}
1075
1076//
1077// This struct exists due to the limitations of the `enum_dispatch` library.
1078//
1079pub trait SuiSignatureInner: Sized + ToFromBytes + PartialEq + Eq + Hash {
1080    type Sig: Authenticator<PubKey = Self::PubKey>;
1081    type PubKey: VerifyingKey<Sig = Self::Sig> + SuiPublicKey;
1082    type KeyPair: KeypairTraits<PubKey = Self::PubKey, Sig = Self::Sig>;
1083
1084    const LENGTH: usize = Self::Sig::LENGTH + Self::PubKey::LENGTH + 1;
1085    const SCHEME: SignatureScheme = Self::PubKey::SIGNATURE_SCHEME;
1086
1087    /// Returns the deserialized signature and deserialized pubkey.
1088    fn get_verification_inputs(&self) -> SuiResult<(Self::Sig, Self::PubKey)> {
1089        let pk = Self::PubKey::from_bytes(self.public_key_bytes())
1090            .map_err(|_| SuiErrorKind::KeyConversionError("Invalid public key".to_string()))?;
1091
1092        // deserialize the signature
1093        let signature = Self::Sig::from_bytes(self.signature_bytes()).map_err(|_| {
1094            SuiErrorKind::InvalidSignature {
1095                error: "Fail to get pubkey and sig".to_string(),
1096            }
1097        })?;
1098
1099        Ok((signature, pk))
1100    }
1101
1102    fn new(kp: &Self::KeyPair, message: &[u8]) -> Self {
1103        let sig = Signer::sign(kp, message);
1104
1105        let mut signature_bytes: Vec<u8> = Vec::new();
1106        signature_bytes
1107            .extend_from_slice(&[<Self::PubKey as SuiPublicKey>::SIGNATURE_SCHEME.flag()]);
1108        signature_bytes.extend_from_slice(sig.as_ref());
1109        signature_bytes.extend_from_slice(kp.public().as_ref());
1110        Self::from_bytes(&signature_bytes[..])
1111            .expect("Serialized signature did not have expected size")
1112    }
1113}
1114
1115pub trait SuiPublicKey: VerifyingKey {
1116    const SIGNATURE_SCHEME: SignatureScheme;
1117}
1118
1119#[enum_dispatch(Signature)]
1120pub trait SuiSignature: Sized + ToFromBytes {
1121    fn signature_bytes(&self) -> &[u8];
1122    fn public_key_bytes(&self) -> &[u8];
1123    fn scheme(&self) -> SignatureScheme;
1124
1125    fn verify_secure<T>(
1126        &self,
1127        value: &IntentMessage<T>,
1128        author: SuiAddress,
1129        scheme: SignatureScheme,
1130    ) -> SuiResult<()>
1131    where
1132        T: Serialize;
1133}
1134
1135impl<S: SuiSignatureInner + Sized> SuiSignature for S {
1136    fn signature_bytes(&self) -> &[u8] {
1137        // Access array slice is safe because the array bytes is initialized as
1138        // flag || signature || pubkey with its defined length.
1139        &self.as_ref()[1..1 + S::Sig::LENGTH]
1140    }
1141
1142    fn public_key_bytes(&self) -> &[u8] {
1143        // Access array slice is safe because the array bytes is initialized as
1144        // flag || signature || pubkey with its defined length.
1145        &self.as_ref()[S::Sig::LENGTH + 1..]
1146    }
1147
1148    fn scheme(&self) -> SignatureScheme {
1149        S::PubKey::SIGNATURE_SCHEME
1150    }
1151
1152    fn verify_secure<T>(
1153        &self,
1154        value: &IntentMessage<T>,
1155        author: SuiAddress,
1156        scheme: SignatureScheme,
1157    ) -> Result<(), SuiError>
1158    where
1159        T: Serialize,
1160    {
1161        let mut hasher = DefaultHash::default();
1162        bcs::serialize_into(&mut hasher, &value).expect("Message serialization should not fail");
1163        let digest = hasher.finalize().digest;
1164
1165        let (sig, pk) = &self.get_verification_inputs()?;
1166        match scheme {
1167            SignatureScheme::ZkLoginAuthenticator => {} // Pass this check because zk login does not derive address from pubkey.
1168            _ => {
1169                let address = SuiAddress::from(pk);
1170                if author != address {
1171                    return Err(SuiErrorKind::IncorrectSigner {
1172                        error: format!(
1173                            "Incorrect signer, expected {:?}, got {:?}",
1174                            author, address
1175                        ),
1176                    }
1177                    .into());
1178                }
1179            }
1180        }
1181
1182        pk.verify(&digest, sig).map_err(|e| {
1183            SuiErrorKind::InvalidSignature {
1184                error: format!("Fail to verify user sig {}", e),
1185            }
1186            .into()
1187        })
1188    }
1189}
1190
1191/// AuthoritySignInfoTrait is a trait used specifically for a few structs in messages.rs
1192/// to template on whether the struct is signed by an authority. We want to limit how
1193/// those structs can be instantiated on, hence the sealed trait.
1194/// TODO: We could also add the aggregated signature as another impl of the trait.
1195///       This will make CertifiedTransaction also an instance of the same struct.
1196pub trait AuthoritySignInfoTrait: private::SealedAuthoritySignInfoTrait {
1197    fn verify_secure<T: Serialize>(
1198        &self,
1199        data: &T,
1200        intent: Intent,
1201        committee: &Committee,
1202    ) -> SuiResult;
1203
1204    fn add_to_verification_obligation<'a>(
1205        &self,
1206        committee: &'a Committee,
1207        obligation: &mut VerificationObligation<'a>,
1208        message_index: usize,
1209    ) -> SuiResult<()>;
1210}
1211
1212#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
1213pub struct EmptySignInfo {}
1214impl AuthoritySignInfoTrait for EmptySignInfo {
1215    fn verify_secure<T: Serialize>(
1216        &self,
1217        _data: &T,
1218        _intent: Intent,
1219        _committee: &Committee,
1220    ) -> SuiResult {
1221        Ok(())
1222    }
1223
1224    fn add_to_verification_obligation<'a>(
1225        &self,
1226        _committee: &'a Committee,
1227        _obligation: &mut VerificationObligation<'a>,
1228        _message_index: usize,
1229    ) -> SuiResult<()> {
1230        Ok(())
1231    }
1232}
1233
1234#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
1235pub struct AuthoritySignInfo {
1236    pub epoch: EpochId,
1237    pub authority: AuthorityName,
1238    pub signature: AuthoritySignature,
1239}
1240
1241impl AuthoritySignInfoTrait for AuthoritySignInfo {
1242    fn verify_secure<T: Serialize>(
1243        &self,
1244        data: &T,
1245        intent: Intent,
1246        committee: &Committee,
1247    ) -> SuiResult<()> {
1248        let mut obligation = VerificationObligation::default();
1249        let idx = obligation.add_message(data, self.epoch, intent);
1250        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1251        obligation.verify_all()?;
1252        Ok(())
1253    }
1254
1255    fn add_to_verification_obligation<'a>(
1256        &self,
1257        committee: &'a Committee,
1258        obligation: &mut VerificationObligation<'a>,
1259        message_index: usize,
1260    ) -> SuiResult<()> {
1261        fp_ensure!(
1262            self.epoch == committee.epoch(),
1263            SuiErrorKind::WrongEpoch {
1264                expected_epoch: committee.epoch(),
1265                actual_epoch: self.epoch,
1266            }
1267            .into()
1268        );
1269        let weight = committee.weight(&self.authority);
1270        fp_ensure!(
1271            weight > 0,
1272            SuiErrorKind::UnknownSigner {
1273                signer: Some(self.authority.concise().to_string()),
1274                index: None,
1275                committee: Box::new(committee.clone())
1276            }
1277            .into()
1278        );
1279
1280        obligation
1281            .public_keys
1282            .get_mut(message_index)
1283            .ok_or(SuiErrorKind::InvalidAddress)?
1284            .push(committee.public_key(&self.authority)?);
1285        obligation
1286            .signatures
1287            .get_mut(message_index)
1288            .ok_or(SuiErrorKind::InvalidAddress)?
1289            .add_signature(self.signature.clone())
1290            .map_err(|_| SuiErrorKind::InvalidSignature {
1291                error: "Fail to aggregator auth sig".to_string(),
1292            })?;
1293        Ok(())
1294    }
1295}
1296
1297impl AuthoritySignInfo {
1298    pub fn new<T>(
1299        epoch: EpochId,
1300        value: &T,
1301        intent: Intent,
1302        name: AuthorityName,
1303        secret: &dyn Signer<AuthoritySignature>,
1304    ) -> Self
1305    where
1306        T: Serialize,
1307    {
1308        Self {
1309            epoch,
1310            authority: name,
1311            signature: AuthoritySignature::new_secure(
1312                &IntentMessage::new(intent, value),
1313                &epoch,
1314                secret,
1315            ),
1316        }
1317    }
1318}
1319
1320impl Hash for AuthoritySignInfo {
1321    fn hash<H: Hasher>(&self, state: &mut H) {
1322        self.epoch.hash(state);
1323        self.authority.hash(state);
1324    }
1325}
1326
1327impl Display for AuthoritySignInfo {
1328    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1329        write!(
1330            f,
1331            "AuthoritySignInfo {{ epoch: {:?}, authority: {} }}",
1332            self.epoch, self.authority,
1333        )
1334    }
1335}
1336
1337impl PartialEq for AuthoritySignInfo {
1338    fn eq(&self, other: &Self) -> bool {
1339        // We do not compare the signature, because there can be multiple
1340        // valid signatures for the same epoch and authority.
1341        self.epoch == other.epoch && self.authority == other.authority
1342    }
1343}
1344
1345/// Represents at least a quorum (could be more) of authority signatures.
1346/// STRONG_THRESHOLD indicates whether to use the quorum threshold for quorum check.
1347/// When STRONG_THRESHOLD is true, the quorum is valid when the total stake is
1348/// at least the quorum threshold (2f+1) of the committee; when STRONG_THRESHOLD is false,
1349/// the quorum is valid when the total stake is at least the validity threshold (f+1) of
1350/// the committee.
1351#[serde_as]
1352#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1353pub struct AuthorityQuorumSignInfo<const STRONG_THRESHOLD: bool> {
1354    pub epoch: EpochId,
1355    #[schemars(with = "Base64")]
1356    pub signature: AggregateAuthoritySignature,
1357    #[schemars(with = "Base64")]
1358    #[serde_as(as = "SuiBitmap")]
1359    pub signers_map: RoaringBitmap,
1360}
1361
1362pub type AuthorityStrongQuorumSignInfo = AuthorityQuorumSignInfo<true>;
1363
1364// Variant of [AuthorityStrongQuorumSignInfo] but with a serialized signature, to be used in
1365// external APIs.
1366#[serde_as]
1367#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1368pub struct SuiAuthorityStrongQuorumSignInfo {
1369    pub epoch: EpochId,
1370    pub signature: AggregateAuthoritySignatureAsBytes,
1371    #[schemars(with = "Base64")]
1372    #[serde_as(as = "SuiBitmap")]
1373    pub signers_map: RoaringBitmap,
1374}
1375
1376impl From<&AuthorityStrongQuorumSignInfo> for SuiAuthorityStrongQuorumSignInfo {
1377    fn from(info: &AuthorityStrongQuorumSignInfo) -> Self {
1378        Self {
1379            epoch: info.epoch,
1380            signature: (&info.signature).into(),
1381            signers_map: info.signers_map.clone(),
1382        }
1383    }
1384}
1385
1386impl TryFrom<&SuiAuthorityStrongQuorumSignInfo> for AuthorityStrongQuorumSignInfo {
1387    type Error = FastCryptoError;
1388
1389    fn try_from(info: &SuiAuthorityStrongQuorumSignInfo) -> Result<Self, Self::Error> {
1390        Ok(Self {
1391            epoch: info.epoch,
1392            signature: (&info.signature).try_into()?,
1393            signers_map: info.signers_map.clone(),
1394        })
1395    }
1396}
1397
1398// Note: if you meet an error due to this line it may be because you need an Eq implementation for `CertifiedTransaction`,
1399// or one of the structs that include it, i.e. `ConfirmationTransaction`, `TransactionInfoResponse` or `ObjectInfoResponse`.
1400//
1401// Please note that any such implementation must be agnostic to the exact set of signatures in the certificate, as
1402// clients are allowed to equivocate on the exact nature of valid certificates they send to the system. This assertion
1403// is a simple tool to make sure certificates are accounted for correctly - should you remove it, you're on your own to
1404// maintain the invariant that valid certificates with distinct signatures are equivalent, but yet-unchecked
1405// certificates that differ on signers aren't.
1406//
1407// see also https://github.com/MystenLabs/sui/issues/266
1408static_assertions::assert_not_impl_any!(AuthorityStrongQuorumSignInfo: Hash, Eq, PartialEq);
1409
1410impl<const STRONG_THRESHOLD: bool> AuthoritySignInfoTrait
1411    for AuthorityQuorumSignInfo<STRONG_THRESHOLD>
1412{
1413    fn verify_secure<T: Serialize>(
1414        &self,
1415        data: &T,
1416        intent: Intent,
1417        committee: &Committee,
1418    ) -> SuiResult {
1419        let mut obligation = VerificationObligation::default();
1420        let idx = obligation.add_message(data, self.epoch, intent);
1421        self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1422        obligation.verify_all()?;
1423        Ok(())
1424    }
1425
1426    fn add_to_verification_obligation<'a>(
1427        &self,
1428        committee: &'a Committee,
1429        obligation: &mut VerificationObligation<'a>,
1430        message_index: usize,
1431    ) -> SuiResult<()> {
1432        // Check epoch
1433        fp_ensure!(
1434            self.epoch == committee.epoch(),
1435            SuiErrorKind::WrongEpoch {
1436                expected_epoch: committee.epoch(),
1437                actual_epoch: self.epoch,
1438            }
1439            .into()
1440        );
1441
1442        let mut weight = 0;
1443
1444        // Create obligations for the committee signatures
1445        obligation
1446            .signatures
1447            .get_mut(message_index)
1448            .ok_or(SuiErrorKind::InvalidAuthenticator)?
1449            .add_aggregate(self.signature.clone())
1450            .map_err(|_| SuiErrorKind::InvalidSignature {
1451                error: "Signature Aggregation failed".to_string(),
1452            })?;
1453
1454        let selected_public_keys = obligation
1455            .public_keys
1456            .get_mut(message_index)
1457            .ok_or(SuiErrorKind::InvalidAuthenticator)?;
1458
1459        let mut seen = std::collections::BTreeSet::new();
1460        for authority_index in self.signers_map.iter() {
1461            if !seen.insert(authority_index) {
1462                continue;
1463            }
1464
1465            // Update weight when seeing the authority for the first time.
1466            let authority = committee
1467                .authority_by_index(authority_index)
1468                .ok_or_else(|| SuiErrorKind::UnknownSigner {
1469                    signer: None,
1470                    index: Some(authority_index),
1471                    committee: Box::new(committee.clone()),
1472                })?;
1473            let voting_rights = committee.weight(authority);
1474            fp_ensure!(
1475                voting_rights > 0,
1476                SuiErrorKind::UnknownSigner {
1477                    signer: Some(authority.concise().to_string()),
1478                    index: Some(authority_index),
1479                    committee: Box::new(committee.clone()),
1480                }
1481                .into()
1482            );
1483            weight += voting_rights;
1484
1485            selected_public_keys.push(committee.public_key(authority)?);
1486        }
1487
1488        fp_ensure!(
1489            weight >= Self::quorum_threshold(committee),
1490            SuiErrorKind::CertificateRequiresQuorum.into()
1491        );
1492
1493        Ok(())
1494    }
1495}
1496
1497impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> {
1498    pub fn new_from_auth_sign_infos(
1499        auth_sign_infos: Vec<AuthoritySignInfo>,
1500        committee: &Committee,
1501    ) -> SuiResult<Self> {
1502        fp_ensure!(
1503            auth_sign_infos.iter().all(|a| a.epoch == committee.epoch),
1504            SuiErrorKind::InvalidSignature {
1505                error: "All signatures must be from the same epoch as the committee".to_string()
1506            }
1507            .into()
1508        );
1509        let total_stake: StakeUnit = auth_sign_infos
1510            .iter()
1511            .map(|a| committee.weight(&a.authority))
1512            .sum();
1513        fp_ensure!(
1514            total_stake >= Self::quorum_threshold(committee),
1515            SuiErrorKind::InvalidSignature {
1516                error: "Signatures don't have enough stake to form a quorum".to_string()
1517            }
1518            .into()
1519        );
1520
1521        let signatures: BTreeMap<_, _> = auth_sign_infos
1522            .into_iter()
1523            .map(|a| (a.authority, a.signature))
1524            .collect();
1525        let mut map = RoaringBitmap::new();
1526        for pk in signatures.keys() {
1527            map.insert(committee.authority_index(pk).ok_or_else(|| {
1528                SuiErrorKind::UnknownSigner {
1529                    signer: Some(pk.concise().to_string()),
1530                    index: None,
1531                    committee: Box::new(committee.clone()),
1532                }
1533            })?);
1534        }
1535        let sigs: Vec<AuthoritySignature> = signatures.into_values().collect();
1536
1537        Ok(AuthorityQuorumSignInfo {
1538            epoch: committee.epoch,
1539            signature: AggregateAuthoritySignature::aggregate(&sigs).map_err(|e| {
1540                SuiErrorKind::InvalidSignature {
1541                    error: e.to_string(),
1542                }
1543            })?,
1544            signers_map: map,
1545        })
1546    }
1547
1548    pub fn authorities<'a>(
1549        &'a self,
1550        committee: &'a Committee,
1551    ) -> impl Iterator<Item = SuiResult<&'a AuthorityName>> {
1552        self.signers_map.iter().map(|i| {
1553            committee
1554                .authority_by_index(i)
1555                .ok_or(SuiErrorKind::InvalidAuthenticator.into())
1556        })
1557    }
1558
1559    pub fn quorum_threshold(committee: &Committee) -> StakeUnit {
1560        committee.threshold::<STRONG_THRESHOLD>()
1561    }
1562
1563    pub fn len(&self) -> u64 {
1564        self.signers_map.len()
1565    }
1566
1567    pub fn is_empty(&self) -> bool {
1568        self.signers_map.is_empty()
1569    }
1570}
1571
1572impl<const S: bool> Display for AuthorityQuorumSignInfo<S> {
1573    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1574        writeln!(
1575            f,
1576            "{} {{ epoch: {:?}, signers_map: {:?} }}",
1577            if S {
1578                "AuthorityStrongQuorumSignInfo"
1579            } else {
1580                "AuthorityWeakQuorumSignInfo"
1581            },
1582            self.epoch,
1583            self.signers_map,
1584        )?;
1585        Ok(())
1586    }
1587}
1588
1589mod private {
1590    pub trait SealedAuthoritySignInfoTrait {}
1591    impl SealedAuthoritySignInfoTrait for super::EmptySignInfo {}
1592    impl SealedAuthoritySignInfoTrait for super::AuthoritySignInfo {}
1593    impl<const S: bool> SealedAuthoritySignInfoTrait for super::AuthorityQuorumSignInfo<S> {}
1594}
1595
1596/// Something that we know how to hash and sign.
1597pub trait Signable<W> {
1598    fn write(&self, writer: &mut W);
1599}
1600
1601pub trait SignableBytes
1602where
1603    Self: Sized,
1604{
1605    fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error>;
1606}
1607
1608/// Activate the blanket implementation of `Signable` based on serde and BCS.
1609/// * We use `serde_name` to extract a seed from the name of structs and enums.
1610/// * We use `BCS` to generate canonical bytes suitable for hashing and signing.
1611///
1612/// # Safety
1613/// We protect the access to this marker trait through a "sealed trait" pattern:
1614/// impls must be add added here (nowehre else) which lets us note those impls
1615/// MUST be on types that comply with the `serde_name` machinery
1616/// for the below implementations not to panic. One way to check they work is to write
1617/// a unit test for serialization to / deserialization from signable bytes.
1618mod bcs_signable {
1619
1620    pub trait BcsSignable: serde::Serialize + serde::de::DeserializeOwned {}
1621    impl BcsSignable for crate::committee::Committee {}
1622    impl BcsSignable for crate::messages_checkpoint::CheckpointSummary {}
1623    impl BcsSignable for crate::messages_checkpoint::CheckpointContents {}
1624
1625    impl BcsSignable for crate::effects::TransactionEffects {}
1626    impl BcsSignable for crate::effects::TransactionEvents {}
1627    impl BcsSignable for crate::transaction::TransactionData {}
1628    impl BcsSignable for crate::transaction::SenderSignedData {}
1629    impl BcsSignable for crate::object::ObjectInner {}
1630
1631    impl BcsSignable for crate::global_state_hash::GlobalStateHash {}
1632
1633    impl BcsSignable for super::bcs_signable_test::Foo {}
1634    #[cfg(test)]
1635    impl BcsSignable for super::bcs_signable_test::Bar {}
1636}
1637
1638impl<T, W> Signable<W> for T
1639where
1640    T: bcs_signable::BcsSignable,
1641    W: std::io::Write,
1642{
1643    fn write(&self, writer: &mut W) {
1644        let name = serde_name::trace_name::<Self>().expect("Self must be a struct or an enum");
1645        // Note: This assumes that names never contain the separator `::`.
1646        write!(writer, "{}::", name).expect("Hasher should not fail");
1647        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1648    }
1649}
1650
1651impl<W> Signable<W> for EpochId
1652where
1653    W: std::io::Write,
1654{
1655    fn write(&self, writer: &mut W) {
1656        bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1657    }
1658}
1659
1660impl<T> SignableBytes for T
1661where
1662    T: bcs_signable::BcsSignable,
1663{
1664    fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error> {
1665        // Remove name tag before deserialization using BCS
1666        let name = serde_name::trace_name::<Self>().expect("Self should be a struct or an enum");
1667        let name_byte_len = format!("{}::", name).bytes().len();
1668        Ok(bcs::from_bytes(bytes.get(name_byte_len..).ok_or_else(
1669            || anyhow!("Failed to deserialize to {name}."),
1670        )?)?)
1671    }
1672}
1673
1674fn hash<S: Signable<H>, H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
1675    signable: &S,
1676) -> [u8; DIGEST_SIZE] {
1677    let mut digest = H::default();
1678    signable.write(&mut digest);
1679    let hash = digest.finalize();
1680    hash.into()
1681}
1682
1683pub fn default_hash<S: Signable<DefaultHash>>(signable: &S) -> [u8; 32] {
1684    hash::<S, DefaultHash, 32>(signable)
1685}
1686
1687#[derive(Default)]
1688pub struct VerificationObligation<'a> {
1689    pub messages: Vec<Vec<u8>>,
1690    pub signatures: Vec<AggregateAuthoritySignature>,
1691    pub public_keys: Vec<Vec<&'a AuthorityPublicKey>>,
1692}
1693
1694impl<'a> VerificationObligation<'a> {
1695    pub fn new() -> VerificationObligation<'a> {
1696        VerificationObligation::default()
1697    }
1698
1699    /// Add a new message to the list of messages to be verified.
1700    /// Returns the index of the message.
1701    pub fn add_message<T>(&mut self, message_value: &T, epoch: EpochId, intent: Intent) -> usize
1702    where
1703        T: Serialize,
1704    {
1705        let intent_msg = IntentMessage::new(intent, message_value);
1706        let mut intent_msg_bytes =
1707            bcs::to_bytes(&intent_msg).expect("Message serialization should not fail");
1708        epoch.write(&mut intent_msg_bytes);
1709        self.signatures.push(AggregateAuthoritySignature::default());
1710        self.public_keys.push(Vec::new());
1711        self.messages.push(intent_msg_bytes);
1712        self.messages.len() - 1
1713    }
1714
1715    // Attempts to add signature and public key to the obligation. If this fails, ensure to call `verify` manually.
1716    pub fn add_signature_and_public_key(
1717        &mut self,
1718        signature: &AuthoritySignature,
1719        public_key: &'a AuthorityPublicKey,
1720        idx: usize,
1721    ) -> SuiResult<()> {
1722        self.public_keys
1723            .get_mut(idx)
1724            .ok_or(SuiErrorKind::InvalidAuthenticator)?
1725            .push(public_key);
1726        self.signatures
1727            .get_mut(idx)
1728            .ok_or(SuiErrorKind::InvalidAuthenticator)?
1729            .add_signature(signature.clone())
1730            .map_err(|_| SuiErrorKind::InvalidSignature {
1731                error: "Failed to add signature to obligation".to_string(),
1732            })?;
1733        Ok(())
1734    }
1735
1736    pub fn verify_all(self) -> SuiResult<()> {
1737        let mut pks = Vec::with_capacity(self.public_keys.len());
1738        for pk in self.public_keys.clone() {
1739            pks.push(pk.into_iter());
1740        }
1741        AggregateAuthoritySignature::batch_verify(
1742            &self.signatures.iter().collect::<Vec<_>>()[..],
1743            pks,
1744            &self.messages.iter().map(|x| &x[..]).collect::<Vec<_>>()[..],
1745        )
1746        .map_err(|e| {
1747            let message = format!(
1748                "pks: {:?}, messages: {:?}, sigs: {:?}",
1749                self.public_keys,
1750                self.messages
1751                    .iter()
1752                    .map(Base64::encode)
1753                    .collect::<Vec<String>>(),
1754                self.signatures
1755                    .iter()
1756                    .map(|s| Base64::encode(s.as_ref()))
1757                    .collect::<Vec<String>>()
1758            );
1759
1760            let chunk_size = 2048;
1761
1762            // This error message may be very long, so we print out the error in chunks of to avoid
1763            // hitting a max log line length on the system.
1764            for (i, chunk) in message
1765                .as_bytes()
1766                .chunks(chunk_size)
1767                .map(std::str::from_utf8)
1768                .enumerate()
1769            {
1770                warn!(
1771                    "Failed to batch verify aggregated auth sig: {} (chunk {}): {}",
1772                    e,
1773                    i,
1774                    chunk.unwrap()
1775                );
1776            }
1777
1778            SuiErrorKind::InvalidSignature {
1779                error: format!("Failed to batch verify aggregated auth sig: {}", e),
1780            }
1781        })?;
1782        Ok(())
1783    }
1784}
1785
1786pub mod bcs_signable_test {
1787    use serde::{Deserialize, Serialize};
1788
1789    #[derive(Clone, Serialize, Deserialize)]
1790    pub struct Foo(pub String);
1791
1792    #[cfg(test)]
1793    #[derive(Serialize, Deserialize)]
1794    pub struct Bar(pub String);
1795
1796    #[cfg(test)]
1797    use super::VerificationObligation;
1798
1799    #[cfg(test)]
1800    pub fn get_obligation_input<T>(value: &T) -> (VerificationObligation<'_>, usize)
1801    where
1802        T: super::bcs_signable::BcsSignable,
1803    {
1804        use shared_crypto::intent::{Intent, IntentScope};
1805
1806        let mut obligation = VerificationObligation::default();
1807        // Add the obligation of the authority signature verifications.
1808        let idx = obligation.add_message(
1809            value,
1810            0,
1811            Intent::sui_app(IntentScope::SenderSignedTransaction),
1812        );
1813        (obligation, idx)
1814    }
1815}
1816
1817#[derive(
1818    Clone,
1819    Copy,
1820    Deserialize,
1821    Serialize,
1822    JsonSchema,
1823    Debug,
1824    EnumString,
1825    strum_macros::Display,
1826    PartialEq,
1827    Eq,
1828)]
1829#[strum(serialize_all = "lowercase")]
1830pub enum SignatureScheme {
1831    ED25519,
1832    Secp256k1,
1833    Secp256r1,
1834    BLS12381, // This is currently not supported for user Sui Address.
1835    MultiSig,
1836    ZkLoginAuthenticator,
1837    PasskeyAuthenticator,
1838    MLDSA65,
1839}
1840
1841impl SignatureScheme {
1842    pub fn flag(&self) -> u8 {
1843        match self {
1844            SignatureScheme::ED25519 => 0x00,
1845            SignatureScheme::Secp256k1 => 0x01,
1846            SignatureScheme::Secp256r1 => 0x02,
1847            SignatureScheme::MultiSig => 0x03,
1848            SignatureScheme::BLS12381 => 0x04, // This is currently not supported for user Sui Address.
1849            SignatureScheme::ZkLoginAuthenticator => 0x05,
1850            SignatureScheme::PasskeyAuthenticator => 0x06,
1851            SignatureScheme::MLDSA65 => 0x07,
1852        }
1853    }
1854
1855    pub fn from_flag(flag: &str) -> Result<SignatureScheme, SuiError> {
1856        let byte_int = flag
1857            .parse::<u8>()
1858            .map_err(|_| SuiErrorKind::KeyConversionError("Invalid key scheme".to_string()))?;
1859        Self::from_flag_byte(&byte_int)
1860    }
1861
1862    pub fn from_flag_byte(byte_int: &u8) -> Result<SignatureScheme, SuiError> {
1863        match byte_int {
1864            0x00 => Ok(SignatureScheme::ED25519),
1865            0x01 => Ok(SignatureScheme::Secp256k1),
1866            0x02 => Ok(SignatureScheme::Secp256r1),
1867            0x03 => Ok(SignatureScheme::MultiSig),
1868            0x04 => Ok(SignatureScheme::BLS12381),
1869            0x05 => Ok(SignatureScheme::ZkLoginAuthenticator),
1870            0x06 => Ok(SignatureScheme::PasskeyAuthenticator),
1871            0x07 => Ok(SignatureScheme::MLDSA65),
1872            _ => Err(SuiErrorKind::KeyConversionError("Invalid key scheme".to_string()).into()),
1873        }
1874    }
1875}
1876/// Unlike [enum Signature], [enum CompressedSignature] does not contain public key.
1877#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1878pub enum CompressedSignature {
1879    Ed25519(Ed25519SignatureAsBytes),
1880    Secp256k1(Secp256k1SignatureAsBytes),
1881    Secp256r1(Secp256r1SignatureAsBytes),
1882    ZkLogin(ZkLoginAuthenticatorAsBytes),
1883    Passkey(PasskeyAuthenticatorAsBytes),
1884    // Boxed and schema-skipped for the same reasons as `PublicKey::MLDSA65`.
1885    #[schemars(skip)]
1886    MLDSA65(Box<MLDSA65SignatureAsBytes>),
1887}
1888
1889#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1890pub struct ZkLoginAuthenticatorAsBytes(#[schemars(with = "Base64")] pub Vec<u8>);
1891
1892#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1893pub struct PasskeyAuthenticatorAsBytes(#[schemars(with = "Base64")] pub Vec<u8>);
1894
1895impl AsRef<[u8]> for CompressedSignature {
1896    fn as_ref(&self) -> &[u8] {
1897        match self {
1898            CompressedSignature::Ed25519(sig) => &sig.0,
1899            CompressedSignature::Secp256k1(sig) => &sig.0,
1900            CompressedSignature::Secp256r1(sig) => &sig.0,
1901            CompressedSignature::ZkLogin(sig) => &sig.0,
1902            CompressedSignature::Passkey(sig) => &sig.0,
1903            CompressedSignature::MLDSA65(sig) => &sig.0,
1904        }
1905    }
1906}
1907
1908impl FromStr for Signature {
1909    type Err = eyre::Report;
1910    fn from_str(s: &str) -> Result<Self, Self::Err> {
1911        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1912    }
1913}
1914
1915impl FromStr for PublicKey {
1916    type Err = eyre::Report;
1917    fn from_str(s: &str) -> Result<Self, Self::Err> {
1918        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1919    }
1920}
1921
1922impl FromStr for GenericSignature {
1923    type Err = eyre::Report;
1924    fn from_str(s: &str) -> Result<Self, Self::Err> {
1925        Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1926    }
1927}
1928
1929//
1930// Types for randomness generation
1931//
1932pub type RandomnessSignature = fastcrypto_tbls::types::Signature;
1933pub type RandomnessPartialSignature = fastcrypto_tbls::tbls::PartialSignature<RandomnessSignature>;
1934pub type RandomnessPrivateKey =
1935    fastcrypto_tbls::ecies_v1::PrivateKey<fastcrypto::groups::bls12381::G2Element>;
1936
1937/// Round number of generated randomness.
1938#[derive(Clone, Copy, Hash, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
1939pub struct RandomnessRound(pub u64);
1940
1941impl Display for RandomnessRound {
1942    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1943        write!(f, "{}", self.0)
1944    }
1945}
1946
1947impl std::ops::Add for RandomnessRound {
1948    type Output = Self;
1949    fn add(self, other: Self) -> Self {
1950        Self(self.0 + other.0)
1951    }
1952}
1953
1954impl std::ops::Add<u64> for RandomnessRound {
1955    type Output = Self;
1956    fn add(self, other: u64) -> Self {
1957        Self(self.0 + other)
1958    }
1959}
1960
1961impl std::ops::Sub for RandomnessRound {
1962    type Output = Self;
1963    fn sub(self, other: Self) -> Self {
1964        Self(self.0 - other.0)
1965    }
1966}
1967
1968impl std::ops::Sub<u64> for RandomnessRound {
1969    type Output = Self;
1970    fn sub(self, other: u64) -> Self {
1971        Self(self.0 - other)
1972    }
1973}
1974
1975impl RandomnessRound {
1976    pub fn new(round: u64) -> Self {
1977        Self(round)
1978    }
1979
1980    pub fn checked_add(self, rhs: u64) -> Option<Self> {
1981        self.0.checked_add(rhs).map(Self)
1982    }
1983
1984    pub fn signature_message(&self) -> Vec<u8> {
1985        "random_beacon round "
1986            .as_bytes()
1987            .iter()
1988            .cloned()
1989            .chain(bcs::to_bytes(&self.0).expect("serialization should not fail"))
1990            .collect()
1991    }
1992}