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