1use 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
64pub type AuthorityKeyPair = BLS12381KeyPair;
66pub type AuthorityPublicKey = BLS12381PublicKey;
67pub type AuthorityPrivateKey = BLS12381PrivateKey;
68pub type AuthoritySignature = BLS12381Signature;
69pub type AggregateAuthoritySignature = BLS12381AggregateSignature;
70pub type AggregateAuthoritySignatureAsBytes = BLS12381AggregateSignatureAsBytes;
71
72pub 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
86pub 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
106pub 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#[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 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 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#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, Serialize, Deserialize)]
275pub struct ZkLoginPublicIdentifier(#[schemars(with = "Base64")] pub Vec<u8>);
276
277impl ZkLoginPublicIdentifier {
278 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#[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 fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
427 ConciseAuthorityPublicKeyBytesRef(self)
428 }
429
430 fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
431 ConciseAuthorityPublicKeyBytes(*self)
432 }
433}
434
435pub 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#[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 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
528pub 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
595pub 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
604pub 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 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
636pub 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
646pub 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#[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 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 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
778impl SuiPublicKey for BLS12381PublicKey {
783 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::BLS12381;
784}
785
786#[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
800impl 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#[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#[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
917pub 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 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 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 &self.as_ref()[1..1 + S::Sig::LENGTH]
981 }
982
983 fn public_key_bytes(&self) -> &[u8] {
984 &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 => {} _ => {
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
1032pub 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 self.epoch == other.epoch && self.authority == other.authority
1183 }
1184}
1185
1186#[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#[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
1239static_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 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 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 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
1437pub 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
1449mod 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 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 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 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 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 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 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, 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, 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#[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
1764pub 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#[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}