1use std::{
6 collections::BTreeMap,
7 fmt::{self, Debug, Display, Formatter},
8 hash::{Hash, Hasher},
9 str::FromStr,
10};
11
12use anyhow::{Error, anyhow};
13use derive_more::{AsMut, AsRef, From};
14pub use enum_dispatch::enum_dispatch;
15use eyre::eyre;
16pub use fastcrypto::traits::{
17 AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair as KeypairTraits, Signer,
18 SigningKey, ToFromBytes, VerifyingKey,
19};
20use fastcrypto::{
21 bls12381::min_sig::{
22 BLS12381AggregateSignature, BLS12381AggregateSignatureAsBytes, BLS12381KeyPair,
23 BLS12381PrivateKey, BLS12381PublicKey, BLS12381Signature,
24 },
25 ed25519::{
26 Ed25519KeyPair, Ed25519PrivateKey, Ed25519PublicKey, Ed25519PublicKeyAsBytes,
27 Ed25519Signature, Ed25519SignatureAsBytes,
28 },
29 encoding::{Base64, Bech32, Encoding, Hex},
30 error::{FastCryptoError, FastCryptoResult},
31 hash::{Blake2b256, HashFunction},
32 secp256k1::{
33 Secp256k1KeyPair, Secp256k1PublicKey, Secp256k1PublicKeyAsBytes, Secp256k1Signature,
34 Secp256k1SignatureAsBytes,
35 },
36 secp256r1::{
37 Secp256r1KeyPair, Secp256r1PublicKey, Secp256r1PublicKeyAsBytes, Secp256r1Signature,
38 Secp256r1SignatureAsBytes,
39 },
40};
41use fastcrypto_zkp::{bn254::zk_login::ZkLoginInputs, zk_login_utils::Bn254FrElement};
42use rand::{
43 SeedableRng,
44 rngs::{OsRng, StdRng},
45};
46use roaring::RoaringBitmap;
47use schemars::JsonSchema;
48use serde::{Deserialize, Deserializer, Serialize, ser::Serializer};
49use serde_with::{Bytes, serde_as};
50use shared_crypto::intent::{Intent, IntentMessage, IntentScope};
51use strum::EnumString;
52use tracing::{instrument, warn};
53
54use crate::{
55 base_types::{AuthorityName, ConciseableName, IotaAddress},
56 committee::{Committee, CommitteeTrait, EpochId, StakeUnit},
57 error::{IotaError, IotaResult},
58 iota_serde::{IotaBitmap, Readable},
59 signature::GenericSignature,
60};
61
62#[cfg(test)]
63#[path = "unit_tests/crypto_tests.rs"]
64mod crypto_tests;
65
66#[cfg(test)]
67#[path = "unit_tests/intent_tests.rs"]
68mod intent_tests;
69
70pub type AuthorityKeyPair = BLS12381KeyPair;
87pub type AuthorityPublicKey = BLS12381PublicKey;
88pub type AuthorityPrivateKey = BLS12381PrivateKey;
89pub type AuthoritySignature = BLS12381Signature;
90pub type AggregateAuthoritySignature = BLS12381AggregateSignature;
91pub type AggregateAuthoritySignatureAsBytes = BLS12381AggregateSignatureAsBytes;
92
93pub type AccountKeyPair = Ed25519KeyPair;
95pub type AccountPublicKey = Ed25519PublicKey;
96pub type AccountPrivateKey = Ed25519PrivateKey;
97
98pub type NetworkKeyPair = Ed25519KeyPair;
99pub type NetworkPublicKey = Ed25519PublicKey;
100pub type NetworkPrivateKey = Ed25519PrivateKey;
101
102pub type DefaultHash = Blake2b256;
103
104pub const DEFAULT_EPOCH_ID: EpochId = 0;
105pub const IOTA_PRIV_KEY_PREFIX: &str = "iotaprivkey";
106
107pub fn generate_proof_of_possession(
114 keypair: &AuthorityKeyPair,
115 address: IotaAddress,
116) -> AuthoritySignature {
117 let mut msg: Vec<u8> = Vec::new();
118 msg.extend_from_slice(keypair.public().as_bytes());
119 msg.extend_from_slice(address.as_ref());
120 AuthoritySignature::new_secure(
121 &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
122 &DEFAULT_EPOCH_ID,
123 keypair,
124 )
125}
126
127pub fn verify_proof_of_possession(
130 pop: &AuthoritySignature,
131 authority_pubkey: &AuthorityPublicKey,
132 iota_address: IotaAddress,
133) -> Result<(), IotaError> {
134 authority_pubkey
135 .validate()
136 .map_err(|_| IotaError::InvalidSignature {
137 error: "Fail to validate pubkey".to_string(),
138 })?;
139 let mut msg = authority_pubkey.as_bytes().to_vec();
140 msg.extend_from_slice(iota_address.as_ref());
141 pop.verify_secure(
142 &IntentMessage::new(Intent::iota_app(IntentScope::ProofOfPossession), msg),
143 DEFAULT_EPOCH_ID,
144 authority_pubkey.into(),
145 )
146}
147
148#[expect(clippy::large_enum_variant)]
155#[derive(Debug, From, PartialEq, Eq)]
156pub enum IotaKeyPair {
157 Ed25519(Ed25519KeyPair),
158 Secp256k1(Secp256k1KeyPair),
159 Secp256r1(Secp256r1KeyPair),
160}
161
162impl IotaKeyPair {
163 pub fn public(&self) -> PublicKey {
164 match self {
165 IotaKeyPair::Ed25519(kp) => PublicKey::Ed25519(kp.public().into()),
166 IotaKeyPair::Secp256k1(kp) => PublicKey::Secp256k1(kp.public().into()),
167 IotaKeyPair::Secp256r1(kp) => PublicKey::Secp256r1(kp.public().into()),
168 }
169 }
170}
171
172impl Clone for IotaKeyPair {
173 fn clone(&self) -> Self {
174 match self {
175 IotaKeyPair::Ed25519(kp) => kp.copy().into(),
176 IotaKeyPair::Secp256k1(kp) => kp.copy().into(),
177 IotaKeyPair::Secp256r1(kp) => kp.copy().into(),
178 }
179 }
180}
181
182impl Signer<Signature> for IotaKeyPair {
183 fn sign(&self, msg: &[u8]) -> Signature {
184 match self {
185 IotaKeyPair::Ed25519(kp) => kp.sign(msg),
186 IotaKeyPair::Secp256k1(kp) => kp.sign(msg),
187 IotaKeyPair::Secp256r1(kp) => kp.sign(msg),
188 }
189 }
190}
191
192impl EncodeDecodeBase64 for IotaKeyPair {
193 fn encode_base64(&self) -> String {
194 Base64::encode(self.to_bytes())
195 }
196
197 fn decode_base64(value: &str) -> FastCryptoResult<Self> {
198 let bytes = Base64::decode(value)?;
199 Self::from_bytes(&bytes).map_err(|_| FastCryptoError::InvalidInput)
200 }
201}
202
203impl IotaKeyPair {
204 pub fn to_bytes(&self) -> Vec<u8> {
205 let mut bytes: Vec<u8> = Vec::new();
206 bytes.push(self.public().flag());
207
208 match self {
209 IotaKeyPair::Ed25519(kp) => {
210 bytes.extend_from_slice(kp.as_bytes());
211 }
212 IotaKeyPair::Secp256k1(kp) => {
213 bytes.extend_from_slice(kp.as_bytes());
214 }
215 IotaKeyPair::Secp256r1(kp) => {
216 bytes.extend_from_slice(kp.as_bytes());
217 }
218 }
219 bytes
220 }
221
222 pub fn from_bytes(bytes: &[u8]) -> Result<Self, eyre::Report> {
223 match SignatureScheme::from_flag_byte(bytes.first().ok_or_else(|| eyre!("Invalid length"))?)
224 {
225 Ok(x) => match x {
226 SignatureScheme::ED25519 => Ok(IotaKeyPair::Ed25519(Ed25519KeyPair::from_bytes(
227 bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
228 )?)),
229 SignatureScheme::Secp256k1 => {
230 Ok(IotaKeyPair::Secp256k1(Secp256k1KeyPair::from_bytes(
231 bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
232 )?))
233 }
234 SignatureScheme::Secp256r1 => {
235 Ok(IotaKeyPair::Secp256r1(Secp256r1KeyPair::from_bytes(
236 bytes.get(1..).ok_or_else(|| eyre!("Invalid length"))?,
237 )?))
238 }
239 _ => Err(eyre!("Invalid flag byte")),
240 },
241 _ => Err(eyre!("Invalid bytes")),
242 }
243 }
244
245 pub fn to_bytes_no_flag(&self) -> Vec<u8> {
246 match self {
247 IotaKeyPair::Ed25519(kp) => kp.as_bytes().to_vec(),
248 IotaKeyPair::Secp256k1(kp) => kp.as_bytes().to_vec(),
249 IotaKeyPair::Secp256r1(kp) => kp.as_bytes().to_vec(),
250 }
251 }
252
253 pub fn encode(&self) -> Result<String, eyre::Report> {
256 Bech32::encode(self.to_bytes(), IOTA_PRIV_KEY_PREFIX).map_err(|e| eyre!(e))
257 }
258
259 pub fn decode(value: &str) -> Result<Self, eyre::Report> {
263 let bytes = Bech32::decode(value, IOTA_PRIV_KEY_PREFIX)?;
264 Self::from_bytes(&bytes)
265 }
266}
267
268impl Serialize for IotaKeyPair {
269 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
270 where
271 S: Serializer,
272 {
273 let s = self.encode_base64();
274 serializer.serialize_str(&s)
275 }
276}
277
278impl<'de> Deserialize<'de> for IotaKeyPair {
279 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
280 where
281 D: Deserializer<'de>,
282 {
283 use serde::de::Error;
284 let s = String::deserialize(deserializer)?;
285 IotaKeyPair::decode_base64(&s).map_err(|e| Error::custom(e.to_string()))
286 }
287}
288
289#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, Serialize, Deserialize)]
290pub enum PublicKey {
291 Ed25519(Ed25519PublicKeyAsBytes),
292 Secp256k1(Secp256k1PublicKeyAsBytes),
293 Secp256r1(Secp256r1PublicKeyAsBytes),
294 ZkLogin(ZkLoginPublicIdentifier),
295 Passkey(Secp256r1PublicKeyAsBytes),
296}
297
298#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, Serialize, Deserialize)]
301pub struct ZkLoginPublicIdentifier(#[schemars(with = "Base64")] pub Vec<u8>);
302
303impl ZkLoginPublicIdentifier {
304 pub fn new(iss: &str, address_seed: &Bn254FrElement) -> IotaResult<Self> {
306 let mut bytes = Vec::new();
307 let iss_bytes = iss.as_bytes();
308 bytes.extend([iss_bytes.len() as u8]);
309 bytes.extend(iss_bytes);
310 bytes.extend(address_seed.padded());
311
312 Ok(Self(bytes))
313 }
314}
315impl AsRef<[u8]> for PublicKey {
316 fn as_ref(&self) -> &[u8] {
317 match self {
318 PublicKey::Ed25519(pk) => &pk.0,
319 PublicKey::Secp256k1(pk) => &pk.0,
320 PublicKey::Secp256r1(pk) => &pk.0,
321 PublicKey::ZkLogin(z) => &z.0,
322 PublicKey::Passkey(pk) => &pk.0,
323 }
324 }
325}
326
327impl EncodeDecodeBase64 for PublicKey {
328 fn encode_base64(&self) -> String {
329 let mut bytes: Vec<u8> = Vec::new();
330 bytes.extend_from_slice(&[self.flag()]);
331 bytes.extend_from_slice(self.as_ref());
332 Base64::encode(&bytes[..])
333 }
334
335 fn decode_base64(value: &str) -> FastCryptoResult<Self> {
336 let bytes = Base64::decode(value)?;
337 match bytes.first() {
338 Some(x) => {
339 if x == &SignatureScheme::ED25519.flag() {
340 let pk: Ed25519PublicKey =
341 Ed25519PublicKey::from_bytes(bytes.get(1..).ok_or(
342 FastCryptoError::InputLengthWrong(Ed25519PublicKey::LENGTH + 1),
343 )?)?;
344 Ok(PublicKey::Ed25519((&pk).into()))
345 } else if x == &SignatureScheme::Secp256k1.flag() {
346 let pk = Secp256k1PublicKey::from_bytes(bytes.get(1..).ok_or(
347 FastCryptoError::InputLengthWrong(Secp256k1PublicKey::LENGTH + 1),
348 )?)?;
349 Ok(PublicKey::Secp256k1((&pk).into()))
350 } else if x == &SignatureScheme::Secp256r1.flag() {
351 let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
352 FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
353 )?)?;
354 Ok(PublicKey::Secp256r1((&pk).into()))
355 } else if x == &SignatureScheme::PasskeyAuthenticator.flag() {
356 let pk = Secp256r1PublicKey::from_bytes(bytes.get(1..).ok_or(
357 FastCryptoError::InputLengthWrong(Secp256r1PublicKey::LENGTH + 1),
358 )?)?;
359 Ok(PublicKey::Passkey((&pk).into()))
360 } else {
361 Err(FastCryptoError::InvalidInput)
362 }
363 }
364 _ => Err(FastCryptoError::InvalidInput),
365 }
366 }
367}
368
369impl PublicKey {
370 pub fn flag(&self) -> u8 {
371 self.scheme().flag()
372 }
373
374 pub fn try_from_bytes(
375 curve: SignatureScheme,
376 key_bytes: &[u8],
377 ) -> Result<PublicKey, eyre::Report> {
378 match curve {
379 SignatureScheme::ED25519 => Ok(PublicKey::Ed25519(
380 (&Ed25519PublicKey::from_bytes(key_bytes)?).into(),
381 )),
382 SignatureScheme::Secp256k1 => Ok(PublicKey::Secp256k1(
383 (&Secp256k1PublicKey::from_bytes(key_bytes)?).into(),
384 )),
385 SignatureScheme::Secp256r1 => Ok(PublicKey::Secp256r1(
386 (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
387 )),
388 SignatureScheme::PasskeyAuthenticator => Ok(PublicKey::Passkey(
389 (&Secp256r1PublicKey::from_bytes(key_bytes)?).into(),
390 )),
391 _ => Err(eyre!("Unsupported curve")),
392 }
393 }
394
395 pub fn scheme(&self) -> SignatureScheme {
396 match self {
397 PublicKey::Ed25519(_) => Ed25519IotaSignature::SCHEME,
398 PublicKey::Secp256k1(_) => Secp256k1IotaSignature::SCHEME,
399 PublicKey::Secp256r1(_) => Secp256r1IotaSignature::SCHEME,
400 PublicKey::ZkLogin(_) => SignatureScheme::ZkLoginAuthenticator,
401 PublicKey::Passkey(_) => SignatureScheme::PasskeyAuthenticator,
402 }
403 }
404
405 pub fn from_zklogin_inputs(inputs: &ZkLoginInputs) -> IotaResult<Self> {
406 Ok(PublicKey::ZkLogin(ZkLoginPublicIdentifier::new(
407 inputs.get_iss(),
408 inputs.get_address_seed(),
409 )?))
410 }
411}
412
413#[serde_as]
416#[derive(
417 Copy,
418 Clone,
419 PartialEq,
420 Eq,
421 Hash,
422 PartialOrd,
423 Ord,
424 Serialize,
425 Deserialize,
426 schemars::JsonSchema,
427 AsRef,
428)]
429#[as_ref(forward)]
430pub struct AuthorityPublicKeyBytes(
431 #[schemars(with = "Base64")]
432 #[serde_as(as = "Readable<Base64, Bytes>")]
433 pub [u8; AuthorityPublicKey::LENGTH],
434);
435
436impl AuthorityPublicKeyBytes {
437 fn fmt_impl(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
438 let s = Hex::encode(self.0);
439 write!(f, "k#{s}")?;
440 Ok(())
441 }
442}
443
444impl<'a> ConciseableName<'a> for AuthorityPublicKeyBytes {
445 type ConciseTypeRef = ConciseAuthorityPublicKeyBytesRef<'a>;
446 type ConciseType = ConciseAuthorityPublicKeyBytes;
447
448 fn concise(&'a self) -> ConciseAuthorityPublicKeyBytesRef<'a> {
453 ConciseAuthorityPublicKeyBytesRef(self)
454 }
455
456 fn concise_owned(&self) -> ConciseAuthorityPublicKeyBytes {
457 ConciseAuthorityPublicKeyBytes(*self)
458 }
459}
460
461pub struct ConciseAuthorityPublicKeyBytesRef<'a>(&'a AuthorityPublicKeyBytes);
463
464impl Debug for ConciseAuthorityPublicKeyBytesRef<'_> {
465 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
466 let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
467 write!(f, "k#{s}..")
468 }
469}
470
471impl Display for ConciseAuthorityPublicKeyBytesRef<'_> {
472 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
473 Debug::fmt(self, f)
474 }
475}
476
477#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, schemars::JsonSchema)]
479pub struct ConciseAuthorityPublicKeyBytes(AuthorityPublicKeyBytes);
480
481impl Debug for ConciseAuthorityPublicKeyBytes {
482 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
483 let s = Hex::encode(self.0.0.get(0..4).ok_or(std::fmt::Error)?);
484 write!(f, "k#{s}..")
485 }
486}
487
488impl Display for ConciseAuthorityPublicKeyBytes {
489 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
490 Debug::fmt(self, f)
491 }
492}
493
494impl TryFrom<AuthorityPublicKeyBytes> for AuthorityPublicKey {
495 type Error = FastCryptoError;
496
497 fn try_from(bytes: AuthorityPublicKeyBytes) -> Result<AuthorityPublicKey, Self::Error> {
498 AuthorityPublicKey::from_bytes(bytes.as_ref())
499 }
500}
501
502impl From<&AuthorityPublicKey> for AuthorityPublicKeyBytes {
503 fn from(pk: &AuthorityPublicKey) -> AuthorityPublicKeyBytes {
504 AuthorityPublicKeyBytes::from_bytes(pk.as_ref()).unwrap()
505 }
506}
507
508impl Debug for AuthorityPublicKeyBytes {
509 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
510 self.fmt_impl(f)
511 }
512}
513
514impl Display for AuthorityPublicKeyBytes {
515 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
516 self.fmt_impl(f)
517 }
518}
519
520impl ToFromBytes for AuthorityPublicKeyBytes {
521 fn from_bytes(bytes: &[u8]) -> Result<Self, fastcrypto::error::FastCryptoError> {
522 let bytes: [u8; AuthorityPublicKey::LENGTH] = bytes
523 .try_into()
524 .map_err(|_| fastcrypto::error::FastCryptoError::InvalidInput)?;
525 Ok(AuthorityPublicKeyBytes(bytes))
526 }
527}
528
529impl AuthorityPublicKeyBytes {
530 pub const ZERO: Self = Self::new([0u8; AuthorityPublicKey::LENGTH]);
531
532 pub const fn new(bytes: [u8; AuthorityPublicKey::LENGTH]) -> AuthorityPublicKeyBytes
535where {
536 AuthorityPublicKeyBytes(bytes)
537 }
538}
539
540impl FromStr for AuthorityPublicKeyBytes {
541 type Err = Error;
542
543 fn from_str(s: &str) -> Result<Self, Self::Err> {
544 let value = Hex::decode(s).map_err(|e| anyhow!(e))?;
545 Self::from_bytes(&value[..]).map_err(|e| anyhow!(e))
546 }
547}
548
549impl Default for AuthorityPublicKeyBytes {
550 fn default() -> Self {
551 Self::ZERO
552 }
553}
554
555pub trait IotaAuthoritySignature {
559 fn verify_secure<T>(
560 &self,
561 value: &IntentMessage<T>,
562 epoch_id: EpochId,
563 author: AuthorityPublicKeyBytes,
564 ) -> Result<(), IotaError>
565 where
566 T: Serialize;
567
568 fn new_secure<T>(
569 value: &IntentMessage<T>,
570 epoch_id: &EpochId,
571 secret: &dyn Signer<Self>,
572 ) -> Self
573 where
574 T: Serialize;
575}
576
577impl IotaAuthoritySignature for AuthoritySignature {
578 #[instrument(level = "trace", skip_all)]
579 fn new_secure<T>(value: &IntentMessage<T>, epoch: &EpochId, secret: &dyn Signer<Self>) -> Self
580 where
581 T: Serialize,
582 {
583 let mut intent_msg_bytes =
584 bcs::to_bytes(&value).expect("Message serialization should not fail");
585 epoch.write(&mut intent_msg_bytes);
586 secret.sign(&intent_msg_bytes)
587 }
588
589 #[instrument(level = "trace", skip_all)]
590 fn verify_secure<T>(
591 &self,
592 value: &IntentMessage<T>,
593 epoch: EpochId,
594 author: AuthorityPublicKeyBytes,
595 ) -> Result<(), IotaError>
596 where
597 T: Serialize,
598 {
599 let mut message = bcs::to_bytes(&value).expect("Message serialization should not fail");
600 epoch.write(&mut message);
601
602 let public_key = AuthorityPublicKey::try_from(author).map_err(|_| {
603 IotaError::KeyConversion(
604 "Failed to serialize public key bytes to valid public key".to_string(),
605 )
606 })?;
607 public_key
608 .verify(&message[..], self)
609 .map_err(|e| IotaError::InvalidSignature {
610 error: format!(
611 "Fail to verify auth sig {} epoch: {} author: {}",
612 e,
613 epoch,
614 author.concise()
615 ),
616 })
617 }
618}
619
620pub fn get_key_pair<KP: KeypairTraits>() -> (IotaAddress, KP)
623where
624 <KP as KeypairTraits>::PubKey: IotaPublicKey,
625{
626 get_key_pair_from_rng(&mut OsRng)
627}
628
629pub fn random_committee_key_pairs_of_size(size: usize) -> Vec<AuthorityKeyPair> {
631 let mut rng = StdRng::from_seed([0; 32]);
632 (0..size)
633 .map(|_| {
634 let key_pair = get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
640 get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut rng);
641 get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
642 get_key_pair_from_rng::<AccountKeyPair, _>(&mut rng);
643 key_pair.1
644 })
645 .collect()
646}
647
648pub fn deterministic_random_account_key() -> (IotaAddress, AccountKeyPair) {
649 let mut rng = StdRng::from_seed([0; 32]);
650 get_key_pair_from_rng(&mut rng)
651}
652
653pub fn get_account_key_pair() -> (IotaAddress, AccountKeyPair) {
654 get_key_pair()
655}
656
657pub fn get_authority_key_pair() -> (IotaAddress, AuthorityKeyPair) {
658 get_key_pair()
659}
660
661pub fn get_key_pair_from_rng<KP: KeypairTraits, R>(csprng: &mut R) -> (IotaAddress, KP)
664where
665 R: rand::CryptoRng + rand::RngCore,
666 <KP as KeypairTraits>::PubKey: IotaPublicKey,
667{
668 let kp = KP::generate(&mut StdRng::from_rng(csprng).unwrap());
669 (kp.public().into(), kp)
670}
671
672pub fn get_key_pair_from_bytes<KP: KeypairTraits>(bytes: &[u8]) -> IotaResult<(IotaAddress, KP)>
674where
675 <KP as KeypairTraits>::PubKey: IotaPublicKey,
676{
677 let priv_length = <KP as KeypairTraits>::PrivKey::LENGTH;
678 let pub_key_length = <KP as KeypairTraits>::PubKey::LENGTH;
679 if bytes.len() != priv_length + pub_key_length {
680 return Err(IotaError::KeyConversion(format!(
681 "Invalid input byte length, expected {}: {}",
682 priv_length,
683 bytes.len()
684 )));
685 }
686 let sk = <KP as KeypairTraits>::PrivKey::from_bytes(
687 bytes
688 .get(..priv_length)
689 .ok_or(IotaError::InvalidPrivateKey)?,
690 )
691 .map_err(|_| IotaError::InvalidPrivateKey)?;
692 let kp: KP = sk.into();
693 Ok((kp.public().into(), kp))
694}
695
696#[enum_dispatch]
701#[derive(Clone, JsonSchema, Debug, PartialEq, Eq, Hash)]
702pub enum Signature {
703 Ed25519IotaSignature,
704 Secp256k1IotaSignature,
705 Secp256r1IotaSignature,
706}
707
708impl Serialize for Signature {
709 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
710 where
711 S: Serializer,
712 {
713 let bytes = self.as_ref();
714
715 if serializer.is_human_readable() {
716 let s = Base64::encode(bytes);
717 serializer.serialize_str(&s)
718 } else {
719 serializer.serialize_bytes(bytes)
720 }
721 }
722}
723
724impl<'de> Deserialize<'de> for Signature {
725 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
726 where
727 D: Deserializer<'de>,
728 {
729 use serde::de::Error;
730
731 let bytes = if deserializer.is_human_readable() {
732 let s = String::deserialize(deserializer)?;
733 Base64::decode(&s).map_err(|e| Error::custom(e.to_string()))?
734 } else {
735 let data: Vec<u8> = Vec::deserialize(deserializer)?;
736 data
737 };
738
739 Self::from_bytes(&bytes).map_err(|e| Error::custom(e.to_string()))
740 }
741}
742
743impl Signature {
744 pub fn new_hashed(hashed_msg: &[u8], secret: &dyn Signer<Signature>) -> Self {
746 Signer::sign(secret, hashed_msg)
747 }
748
749 pub fn new_secure<T>(value: &IntentMessage<T>, secret: &dyn Signer<Signature>) -> Self
750 where
751 T: Serialize,
752 {
753 let mut hasher = DefaultHash::default();
759 hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
760
761 Signer::sign(secret, &hasher.finalize().digest)
762 }
763}
764
765impl AsRef<[u8]> for Signature {
766 fn as_ref(&self) -> &[u8] {
767 match self {
768 Signature::Ed25519IotaSignature(sig) => sig.as_ref(),
769 Signature::Secp256k1IotaSignature(sig) => sig.as_ref(),
770 Signature::Secp256r1IotaSignature(sig) => sig.as_ref(),
771 }
772 }
773}
774impl AsMut<[u8]> for Signature {
775 fn as_mut(&mut self) -> &mut [u8] {
776 match self {
777 Signature::Ed25519IotaSignature(sig) => sig.as_mut(),
778 Signature::Secp256k1IotaSignature(sig) => sig.as_mut(),
779 Signature::Secp256r1IotaSignature(sig) => sig.as_mut(),
780 }
781 }
782}
783
784impl ToFromBytes for Signature {
785 fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
786 match bytes.first() {
787 Some(x) => {
788 if x == &Ed25519IotaSignature::SCHEME.flag() {
789 Ok(<Ed25519IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
790 } else if x == &Secp256k1IotaSignature::SCHEME.flag() {
791 Ok(<Secp256k1IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
792 } else if x == &Secp256r1IotaSignature::SCHEME.flag() {
793 Ok(<Secp256r1IotaSignature as ToFromBytes>::from_bytes(bytes)?.into())
794 } else {
795 Err(FastCryptoError::InvalidInput)
796 }
797 }
798 _ => Err(FastCryptoError::InvalidInput),
799 }
800 }
801}
802
803impl IotaPublicKey for BLS12381PublicKey {
807 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::BLS12381;
808}
809
810#[serde_as]
814#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
815#[as_ref(forward)]
816#[as_mut(forward)]
817pub struct Ed25519IotaSignature(
818 #[schemars(with = "Base64")]
819 #[serde_as(as = "Readable<Base64, Bytes>")]
820 [u8; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1],
821);
822
823impl Default for Ed25519IotaSignature {
825 fn default() -> Self {
826 Self([0; Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1])
827 }
828}
829
830impl IotaSignatureInner for Ed25519IotaSignature {
831 type Sig = Ed25519Signature;
832 type PubKey = Ed25519PublicKey;
833 type KeyPair = Ed25519KeyPair;
834 const LENGTH: usize = Ed25519PublicKey::LENGTH + Ed25519Signature::LENGTH + 1;
835}
836
837impl IotaPublicKey for Ed25519PublicKey {
838 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::ED25519;
839}
840
841impl ToFromBytes for Ed25519IotaSignature {
842 fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
843 if bytes.len() != Self::LENGTH {
844 return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
845 }
846 let mut sig_bytes = [0; Self::LENGTH];
847 sig_bytes.copy_from_slice(bytes);
848 Ok(Self(sig_bytes))
849 }
850}
851
852impl Signer<Signature> for Ed25519KeyPair {
853 fn sign(&self, msg: &[u8]) -> Signature {
854 Ed25519IotaSignature::new(self, msg).into()
855 }
856}
857
858#[serde_as]
861#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
862#[as_ref(forward)]
863#[as_mut(forward)]
864pub struct Secp256k1IotaSignature(
865 #[schemars(with = "Base64")]
866 #[serde_as(as = "Readable<Base64, Bytes>")]
867 [u8; Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1],
868);
869
870impl IotaSignatureInner for Secp256k1IotaSignature {
871 type Sig = Secp256k1Signature;
872 type PubKey = Secp256k1PublicKey;
873 type KeyPair = Secp256k1KeyPair;
874 const LENGTH: usize = Secp256k1PublicKey::LENGTH + Secp256k1Signature::LENGTH + 1;
875}
876
877impl IotaPublicKey for Secp256k1PublicKey {
878 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256k1;
879}
880
881impl ToFromBytes for Secp256k1IotaSignature {
882 fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
883 if bytes.len() != Self::LENGTH {
884 return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
885 }
886 let mut sig_bytes = [0; Self::LENGTH];
887 sig_bytes.copy_from_slice(bytes);
888 Ok(Self(sig_bytes))
889 }
890}
891
892impl Signer<Signature> for Secp256k1KeyPair {
893 fn sign(&self, msg: &[u8]) -> Signature {
894 Secp256k1IotaSignature::new(self, msg).into()
895 }
896}
897
898#[serde_as]
901#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, AsRef, AsMut)]
902#[as_ref(forward)]
903#[as_mut(forward)]
904pub struct Secp256r1IotaSignature(
905 #[schemars(with = "Base64")]
906 #[serde_as(as = "Readable<Base64, Bytes>")]
907 [u8; Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1],
908);
909
910impl IotaSignatureInner for Secp256r1IotaSignature {
911 type Sig = Secp256r1Signature;
912 type PubKey = Secp256r1PublicKey;
913 type KeyPair = Secp256r1KeyPair;
914 const LENGTH: usize = Secp256r1PublicKey::LENGTH + Secp256r1Signature::LENGTH + 1;
915}
916
917impl IotaPublicKey for Secp256r1PublicKey {
918 const SIGNATURE_SCHEME: SignatureScheme = SignatureScheme::Secp256r1;
919}
920
921impl ToFromBytes for Secp256r1IotaSignature {
922 fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
923 if bytes.len() != Self::LENGTH {
924 return Err(FastCryptoError::InputLengthWrong(Self::LENGTH));
925 }
926 let mut sig_bytes = [0; Self::LENGTH];
927 sig_bytes.copy_from_slice(bytes);
928 Ok(Self(sig_bytes))
929 }
930}
931
932impl Signer<Signature> for Secp256r1KeyPair {
933 fn sign(&self, msg: &[u8]) -> Signature {
934 Secp256r1IotaSignature::new(self, msg).into()
935 }
936}
937
938pub trait IotaSignatureInner: Sized + ToFromBytes + PartialEq + Eq + Hash {
941 type Sig: Authenticator<PubKey = Self::PubKey>;
942 type PubKey: VerifyingKey<Sig = Self::Sig> + IotaPublicKey;
943 type KeyPair: KeypairTraits<PubKey = Self::PubKey, Sig = Self::Sig>;
944
945 const LENGTH: usize = Self::Sig::LENGTH + Self::PubKey::LENGTH + 1;
946 const SCHEME: SignatureScheme = Self::PubKey::SIGNATURE_SCHEME;
947
948 fn get_verification_inputs(&self) -> IotaResult<(Self::Sig, Self::PubKey)> {
950 let pk = Self::PubKey::from_bytes(self.public_key_bytes())
951 .map_err(|_| IotaError::KeyConversion("Invalid public key".to_string()))?;
952
953 let signature = Self::Sig::from_bytes(self.signature_bytes()).map_err(|_| {
955 IotaError::InvalidSignature {
956 error: "Fail to get pubkey and sig".to_string(),
957 }
958 })?;
959
960 Ok((signature, pk))
961 }
962
963 fn new(kp: &Self::KeyPair, message: &[u8]) -> Self {
964 let sig = Signer::sign(kp, message);
965
966 let mut signature_bytes: Vec<u8> = Vec::new();
967 signature_bytes
968 .extend_from_slice(&[<Self::PubKey as IotaPublicKey>::SIGNATURE_SCHEME.flag()]);
969 signature_bytes.extend_from_slice(sig.as_ref());
970 signature_bytes.extend_from_slice(kp.public().as_ref());
971 Self::from_bytes(&signature_bytes[..])
972 .expect("Serialized signature did not have expected size")
973 }
974}
975
976pub trait IotaPublicKey: VerifyingKey {
977 const SIGNATURE_SCHEME: SignatureScheme;
978}
979
980#[enum_dispatch(Signature)]
981pub trait IotaSignature: Sized + ToFromBytes {
982 fn signature_bytes(&self) -> &[u8];
983 fn public_key_bytes(&self) -> &[u8];
984 fn scheme(&self) -> SignatureScheme;
985
986 fn verify_secure<T>(
987 &self,
988 value: &IntentMessage<T>,
989 author: IotaAddress,
990 scheme: SignatureScheme,
991 ) -> IotaResult<()>
992 where
993 T: Serialize;
994}
995
996impl<S: IotaSignatureInner + Sized> IotaSignature for S {
997 fn signature_bytes(&self) -> &[u8] {
998 &self.as_ref()[1..1 + S::Sig::LENGTH]
1001 }
1002
1003 fn public_key_bytes(&self) -> &[u8] {
1004 &self.as_ref()[S::Sig::LENGTH + 1..]
1007 }
1008
1009 fn scheme(&self) -> SignatureScheme {
1010 S::PubKey::SIGNATURE_SCHEME
1011 }
1012
1013 fn verify_secure<T>(
1014 &self,
1015 value: &IntentMessage<T>,
1016 author: IotaAddress,
1017 scheme: SignatureScheme,
1018 ) -> Result<(), IotaError>
1019 where
1020 T: Serialize,
1021 {
1022 let mut hasher = DefaultHash::default();
1023 hasher.update(bcs::to_bytes(&value).expect("Message serialization should not fail"));
1024 let digest = hasher.finalize().digest;
1025
1026 let (sig, pk) = &self.get_verification_inputs()?;
1027 match scheme {
1028 SignatureScheme::ZkLoginAuthenticator => {} _ => {
1031 let address = IotaAddress::from(pk);
1032 if author != address {
1033 return Err(IotaError::IncorrectSigner {
1034 error: format!("Incorrect signer, expected {author:?}, got {address:?}"),
1035 });
1036 }
1037 }
1038 }
1039
1040 pk.verify(&digest, sig)
1041 .map_err(|e| IotaError::InvalidSignature {
1042 error: format!("Fail to verify user sig {e}"),
1043 })
1044 }
1045}
1046
1047pub trait AuthoritySignInfoTrait: private::SealedAuthoritySignInfoTrait {
1054 fn verify_secure<T: Serialize>(
1055 &self,
1056 data: &T,
1057 intent: Intent,
1058 committee: &Committee,
1059 ) -> IotaResult;
1060
1061 fn add_to_verification_obligation<'a>(
1062 &self,
1063 committee: &'a Committee,
1064 obligation: &mut VerificationObligation<'a>,
1065 message_index: usize,
1066 ) -> IotaResult<()>;
1067}
1068
1069#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
1070pub struct EmptySignInfo {}
1071impl AuthoritySignInfoTrait for EmptySignInfo {
1072 fn verify_secure<T: Serialize>(
1073 &self,
1074 _data: &T,
1075 _intent: Intent,
1076 _committee: &Committee,
1077 ) -> IotaResult {
1078 Ok(())
1079 }
1080
1081 fn add_to_verification_obligation<'a>(
1082 &self,
1083 _committee: &'a Committee,
1084 _obligation: &mut VerificationObligation<'a>,
1085 _message_index: usize,
1086 ) -> IotaResult<()> {
1087 Ok(())
1088 }
1089}
1090
1091#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
1092pub struct AuthoritySignInfo {
1093 pub epoch: EpochId,
1094 pub authority: AuthorityName,
1095 pub signature: AuthoritySignature,
1096}
1097
1098impl AuthoritySignInfoTrait for AuthoritySignInfo {
1099 fn verify_secure<T: Serialize>(
1100 &self,
1101 data: &T,
1102 intent: Intent,
1103 committee: &Committee,
1104 ) -> IotaResult<()> {
1105 let mut obligation = VerificationObligation::default();
1106 let idx = obligation.add_message(data, self.epoch, intent);
1107 self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1108 obligation.verify_all()?;
1109 Ok(())
1110 }
1111
1112 fn add_to_verification_obligation<'a>(
1113 &self,
1114 committee: &'a Committee,
1115 obligation: &mut VerificationObligation<'a>,
1116 message_index: usize,
1117 ) -> IotaResult<()> {
1118 fp_ensure!(
1119 self.epoch == committee.epoch(),
1120 IotaError::WrongEpoch {
1121 expected_epoch: committee.epoch(),
1122 actual_epoch: self.epoch,
1123 }
1124 );
1125 let weight = committee.weight(&self.authority);
1126 fp_ensure!(
1127 weight > 0,
1128 IotaError::UnknownSigner {
1129 signer: Some(self.authority.concise().to_string()),
1130 index: None,
1131 committee: Box::new(committee.clone())
1132 }
1133 );
1134
1135 obligation
1136 .public_keys
1137 .get_mut(message_index)
1138 .ok_or(IotaError::InvalidAddress)?
1139 .push(committee.public_key(&self.authority)?);
1140 obligation
1141 .signatures
1142 .get_mut(message_index)
1143 .ok_or(IotaError::InvalidAddress)?
1144 .add_signature(self.signature.clone())
1145 .map_err(|_| IotaError::InvalidSignature {
1146 error: "Fail to aggregator auth sig".to_string(),
1147 })?;
1148 Ok(())
1149 }
1150}
1151
1152impl AuthoritySignInfo {
1153 pub fn new<T>(
1154 epoch: EpochId,
1155 value: &T,
1156 intent: Intent,
1157 name: AuthorityName,
1158 secret: &dyn Signer<AuthoritySignature>,
1159 ) -> Self
1160 where
1161 T: Serialize,
1162 {
1163 Self {
1164 epoch,
1165 authority: name,
1166 signature: AuthoritySignature::new_secure(
1167 &IntentMessage::new(intent, value),
1168 &epoch,
1169 secret,
1170 ),
1171 }
1172 }
1173}
1174
1175impl Hash for AuthoritySignInfo {
1176 fn hash<H: Hasher>(&self, state: &mut H) {
1177 self.epoch.hash(state);
1178 self.authority.hash(state);
1179 }
1180}
1181
1182impl Display for AuthoritySignInfo {
1183 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1184 write!(
1185 f,
1186 "AuthoritySignInfo {{ epoch: {:?}, authority: {} }}",
1187 self.epoch, self.authority,
1188 )
1189 }
1190}
1191
1192impl PartialEq for AuthoritySignInfo {
1193 fn eq(&self, other: &Self) -> bool {
1194 self.epoch == other.epoch && self.authority == other.authority
1197 }
1198}
1199
1200#[serde_as]
1207#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1208pub struct AuthorityQuorumSignInfo<const STRONG_THRESHOLD: bool> {
1209 pub epoch: EpochId,
1210 #[schemars(with = "Base64")]
1211 pub signature: AggregateAuthoritySignature,
1212 #[schemars(with = "Base64")]
1213 #[serde_as(as = "IotaBitmap")]
1214 pub signers_map: RoaringBitmap,
1215}
1216
1217pub type AuthorityStrongQuorumSignInfo = AuthorityQuorumSignInfo<true>;
1218
1219#[serde_as]
1222#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1223pub struct IotaAuthorityStrongQuorumSignInfo {
1224 pub epoch: EpochId,
1225 pub signature: AggregateAuthoritySignatureAsBytes,
1226 #[schemars(with = "Base64")]
1227 #[serde_as(as = "IotaBitmap")]
1228 pub signers_map: RoaringBitmap,
1229}
1230
1231impl From<&AuthorityStrongQuorumSignInfo> for IotaAuthorityStrongQuorumSignInfo {
1232 fn from(info: &AuthorityStrongQuorumSignInfo) -> Self {
1233 Self {
1234 epoch: info.epoch,
1235 signature: (&info.signature).into(),
1236 signers_map: info.signers_map.clone(),
1237 }
1238 }
1239}
1240
1241impl TryFrom<&IotaAuthorityStrongQuorumSignInfo> for AuthorityStrongQuorumSignInfo {
1242 type Error = FastCryptoError;
1243
1244 fn try_from(info: &IotaAuthorityStrongQuorumSignInfo) -> Result<Self, Self::Error> {
1245 Ok(Self {
1246 epoch: info.epoch,
1247 signature: (&info.signature).try_into()?,
1248 signers_map: info.signers_map.clone(),
1249 })
1250 }
1251}
1252
1253static_assertions::assert_not_impl_any!(AuthorityStrongQuorumSignInfo: Hash, Eq, PartialEq);
1268
1269impl<const STRONG_THRESHOLD: bool> AuthoritySignInfoTrait
1270 for AuthorityQuorumSignInfo<STRONG_THRESHOLD>
1271{
1272 fn verify_secure<T: Serialize>(
1273 &self,
1274 data: &T,
1275 intent: Intent,
1276 committee: &Committee,
1277 ) -> IotaResult {
1278 let mut obligation = VerificationObligation::default();
1279 let idx = obligation.add_message(data, self.epoch, intent);
1280 self.add_to_verification_obligation(committee, &mut obligation, idx)?;
1281 obligation.verify_all()?;
1282 Ok(())
1283 }
1284
1285 fn add_to_verification_obligation<'a>(
1286 &self,
1287 committee: &'a Committee,
1288 obligation: &mut VerificationObligation<'a>,
1289 message_index: usize,
1290 ) -> IotaResult<()> {
1291 fp_ensure!(
1293 self.epoch == committee.epoch(),
1294 IotaError::WrongEpoch {
1295 expected_epoch: committee.epoch(),
1296 actual_epoch: self.epoch,
1297 }
1298 );
1299
1300 let mut weight = 0;
1301
1302 obligation
1304 .signatures
1305 .get_mut(message_index)
1306 .ok_or(IotaError::InvalidAuthenticator)?
1307 .add_aggregate(self.signature.clone())
1308 .map_err(|_| IotaError::InvalidSignature {
1309 error: "Signature Aggregation failed".to_string(),
1310 })?;
1311
1312 let selected_public_keys = obligation
1313 .public_keys
1314 .get_mut(message_index)
1315 .ok_or(IotaError::InvalidAuthenticator)?;
1316
1317 for authority_index in self.signers_map.iter() {
1318 let authority = committee
1319 .authority_by_index(authority_index)
1320 .ok_or_else(|| IotaError::UnknownSigner {
1321 signer: None,
1322 index: Some(authority_index),
1323 committee: Box::new(committee.clone()),
1324 })?;
1325
1326 let voting_rights = committee.weight(authority);
1328 fp_ensure!(
1329 voting_rights > 0,
1330 IotaError::UnknownSigner {
1331 signer: Some(authority.concise().to_string()),
1332 index: Some(authority_index),
1333 committee: Box::new(committee.clone()),
1334 }
1335 );
1336 weight += voting_rights;
1337
1338 selected_public_keys.push(committee.public_key(authority)?);
1339 }
1340
1341 fp_ensure!(
1342 weight >= Self::quorum_threshold(committee),
1343 IotaError::CertificateRequiresQuorum
1344 );
1345
1346 Ok(())
1347 }
1348}
1349
1350impl<const STRONG_THRESHOLD: bool> AuthorityQuorumSignInfo<STRONG_THRESHOLD> {
1351 pub fn new_from_auth_sign_infos(
1352 auth_sign_infos: Vec<AuthoritySignInfo>,
1353 committee: &Committee,
1354 ) -> IotaResult<Self> {
1355 fp_ensure!(
1356 auth_sign_infos.iter().all(|a| a.epoch == committee.epoch),
1357 IotaError::InvalidSignature {
1358 error: "All signatures must be from the same epoch as the committee".to_string()
1359 }
1360 );
1361 let total_stake: StakeUnit = auth_sign_infos
1362 .iter()
1363 .map(|a| committee.weight(&a.authority))
1364 .sum();
1365 fp_ensure!(
1366 total_stake >= Self::quorum_threshold(committee),
1367 IotaError::InvalidSignature {
1368 error: "Signatures don't have enough stake to form a quorum".to_string()
1369 }
1370 );
1371
1372 let signatures: BTreeMap<_, _> = auth_sign_infos
1373 .into_iter()
1374 .map(|a| (a.authority, a.signature))
1375 .collect();
1376 let mut map = RoaringBitmap::new();
1377 for pk in signatures.keys() {
1378 map.insert(
1379 committee
1380 .authority_index(pk)
1381 .ok_or_else(|| IotaError::UnknownSigner {
1382 signer: Some(pk.concise().to_string()),
1383 index: None,
1384 committee: Box::new(committee.clone()),
1385 })?,
1386 );
1387 }
1388 let sigs: Vec<AuthoritySignature> = signatures.into_values().collect();
1389
1390 Ok(AuthorityQuorumSignInfo {
1391 epoch: committee.epoch,
1392 signature: AggregateAuthoritySignature::aggregate(&sigs).map_err(|e| {
1393 IotaError::InvalidSignature {
1394 error: e.to_string(),
1395 }
1396 })?,
1397 signers_map: map,
1398 })
1399 }
1400
1401 pub fn authorities<'a>(
1402 &'a self,
1403 committee: &'a Committee,
1404 ) -> impl Iterator<Item = IotaResult<&'a AuthorityName>> {
1405 self.signers_map.iter().map(|i| {
1406 committee
1407 .authority_by_index(i)
1408 .ok_or(IotaError::InvalidAuthenticator)
1409 })
1410 }
1411
1412 pub fn quorum_threshold(committee: &Committee) -> StakeUnit {
1413 committee.threshold::<STRONG_THRESHOLD>()
1414 }
1415
1416 pub fn len(&self) -> u64 {
1417 self.signers_map.len()
1418 }
1419
1420 pub fn is_empty(&self) -> bool {
1421 self.signers_map.is_empty()
1422 }
1423}
1424
1425impl<const S: bool> Display for AuthorityQuorumSignInfo<S> {
1426 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1427 writeln!(
1428 f,
1429 "{} {{ epoch: {:?}, signers_map: {:?} }}",
1430 if S {
1431 "AuthorityStrongQuorumSignInfo"
1432 } else {
1433 "AuthorityWeakQuorumSignInfo"
1434 },
1435 self.epoch,
1436 self.signers_map,
1437 )?;
1438 Ok(())
1439 }
1440}
1441
1442mod private {
1443 pub trait SealedAuthoritySignInfoTrait {}
1444 impl SealedAuthoritySignInfoTrait for super::EmptySignInfo {}
1445 impl SealedAuthoritySignInfoTrait for super::AuthoritySignInfo {}
1446 impl<const S: bool> SealedAuthoritySignInfoTrait for super::AuthorityQuorumSignInfo<S> {}
1447}
1448
1449pub trait Signable<W> {
1451 fn write(&self, writer: &mut W);
1452}
1453
1454pub trait SignableBytes
1455where
1456 Self: Sized,
1457{
1458 fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error>;
1459}
1460
1461mod bcs_signable {
1473
1474 pub trait BcsSignable: serde::Serialize + serde::de::DeserializeOwned {}
1475 impl BcsSignable for crate::committee::Committee {}
1476 impl BcsSignable for crate::messages_checkpoint::CheckpointSummary {}
1477 impl BcsSignable for crate::messages_checkpoint::CheckpointContents {}
1478
1479 impl BcsSignable for crate::effects::TransactionEffects {}
1480 impl BcsSignable for crate::effects::TransactionEvents {}
1481 impl BcsSignable for crate::transaction::TransactionData {}
1482 impl BcsSignable for crate::transaction::SenderSignedData {}
1483 impl BcsSignable for crate::object::ObjectInner {}
1484
1485 impl BcsSignable for crate::accumulator::Accumulator {}
1486
1487 impl BcsSignable for super::bcs_signable_test::Foo {}
1488 #[cfg(test)]
1489 impl BcsSignable for super::bcs_signable_test::Bar {}
1490}
1491
1492impl<T, W> Signable<W> for T
1493where
1494 T: bcs_signable::BcsSignable,
1495 W: std::io::Write,
1496{
1497 fn write(&self, writer: &mut W) {
1498 let name = serde_name::trace_name::<Self>().expect("Self must be a struct or an enum");
1499 write!(writer, "{name}::").expect("Hasher should not fail");
1501 bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1502 }
1503}
1504
1505impl<W> Signable<W> for EpochId
1506where
1507 W: std::io::Write,
1508{
1509 fn write(&self, writer: &mut W) {
1510 bcs::serialize_into(writer, &self).expect("Message serialization should not fail");
1511 }
1512}
1513
1514impl<T> SignableBytes for T
1515where
1516 T: bcs_signable::BcsSignable,
1517{
1518 fn from_signable_bytes(bytes: &[u8]) -> Result<Self, Error> {
1519 let name = serde_name::trace_name::<Self>().expect("Self should be a struct or an enum");
1521 let name_byte_len = format!("{name}::").bytes().len();
1522 Ok(bcs::from_bytes(bytes.get(name_byte_len..).ok_or_else(
1523 || anyhow!("Failed to deserialize to {name}."),
1524 )?)?)
1525 }
1526}
1527
1528fn hash<S: Signable<H>, H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
1529 signable: &S,
1530) -> [u8; DIGEST_SIZE] {
1531 let mut digest = H::default();
1532 signable.write(&mut digest);
1533 let hash = digest.finalize();
1534 hash.into()
1535}
1536
1537pub fn default_hash<S: Signable<DefaultHash>>(signable: &S) -> [u8; 32] {
1538 hash::<S, DefaultHash, 32>(signable)
1539}
1540
1541#[derive(Default)]
1542pub struct VerificationObligation<'a> {
1543 pub messages: Vec<Vec<u8>>,
1544 pub signatures: Vec<AggregateAuthoritySignature>,
1545 pub public_keys: Vec<Vec<&'a AuthorityPublicKey>>,
1546}
1547
1548impl<'a> VerificationObligation<'a> {
1549 pub fn new() -> VerificationObligation<'a> {
1550 VerificationObligation::default()
1551 }
1552
1553 pub fn add_message<T>(&mut self, message_value: &T, epoch: EpochId, intent: Intent) -> usize
1556 where
1557 T: Serialize,
1558 {
1559 let intent_msg = IntentMessage::new(intent, message_value);
1560 let mut intent_msg_bytes =
1561 bcs::to_bytes(&intent_msg).expect("Message serialization should not fail");
1562 epoch.write(&mut intent_msg_bytes);
1563 self.signatures.push(AggregateAuthoritySignature::default());
1564 self.public_keys.push(Vec::new());
1565 self.messages.push(intent_msg_bytes);
1566 self.messages.len() - 1
1567 }
1568
1569 pub fn add_signature_and_public_key(
1572 &mut self,
1573 signature: &AuthoritySignature,
1574 public_key: &'a AuthorityPublicKey,
1575 idx: usize,
1576 ) -> IotaResult<()> {
1577 self.public_keys
1578 .get_mut(idx)
1579 .ok_or(IotaError::InvalidAuthenticator)?
1580 .push(public_key);
1581 self.signatures
1582 .get_mut(idx)
1583 .ok_or(IotaError::InvalidAuthenticator)?
1584 .add_signature(signature.clone())
1585 .map_err(|_| IotaError::InvalidSignature {
1586 error: "Failed to add signature to obligation".to_string(),
1587 })?;
1588 Ok(())
1589 }
1590
1591 pub fn verify_all(self) -> IotaResult<()> {
1592 let mut pks = Vec::with_capacity(self.public_keys.len());
1593 for pk in self.public_keys.clone() {
1594 pks.push(pk.into_iter());
1595 }
1596 AggregateAuthoritySignature::batch_verify(
1597 &self.signatures.iter().collect::<Vec<_>>()[..],
1598 pks,
1599 &self.messages.iter().map(|x| &x[..]).collect::<Vec<_>>()[..],
1600 )
1601 .map_err(|e| {
1602 let message = format!(
1603 "pks: {:?}, messages: {:?}, sigs: {:?}",
1604 &self.public_keys,
1605 self.messages
1606 .iter()
1607 .map(Base64::encode)
1608 .collect::<Vec<String>>(),
1609 &self
1610 .signatures
1611 .iter()
1612 .map(|s| Base64::encode(s.as_ref()))
1613 .collect::<Vec<String>>()
1614 );
1615
1616 let chunk_size = 2048;
1617
1618 for (i, chunk) in message
1621 .as_bytes()
1622 .chunks(chunk_size)
1623 .map(std::str::from_utf8)
1624 .enumerate()
1625 {
1626 warn!(
1627 "Failed to batch verify aggregated auth sig: {} (chunk {}): {}",
1628 e,
1629 i,
1630 chunk.unwrap()
1631 );
1632 }
1633
1634 IotaError::InvalidSignature {
1635 error: format!("Failed to batch verify aggregated auth sig: {e}"),
1636 }
1637 })?;
1638 Ok(())
1639 }
1640}
1641
1642pub mod bcs_signable_test {
1643 use serde::{Deserialize, Serialize};
1644
1645 #[derive(Clone, Serialize, Deserialize)]
1646 pub struct Foo(pub String);
1647
1648 #[cfg(test)]
1649 #[derive(Serialize, Deserialize)]
1650 pub struct Bar(pub String);
1651
1652 #[cfg(test)]
1653 use super::VerificationObligation;
1654
1655 #[cfg(test)]
1656 pub fn get_obligation_input<T>(value: &T) -> (VerificationObligation<'_>, usize)
1657 where
1658 T: super::bcs_signable::BcsSignable,
1659 {
1660 use shared_crypto::intent::{Intent, IntentScope};
1661
1662 let mut obligation = VerificationObligation::default();
1663 let idx = obligation.add_message(
1665 value,
1666 0,
1667 Intent::iota_app(IntentScope::SenderSignedTransaction),
1668 );
1669 (obligation, idx)
1670 }
1671}
1672
1673#[derive(
1674 Clone,
1675 Copy,
1676 Deserialize,
1677 Serialize,
1678 JsonSchema,
1679 Debug,
1680 EnumString,
1681 strum_macros::Display,
1682 PartialEq,
1683 Eq,
1684)]
1685#[strum(serialize_all = "lowercase")]
1686pub enum SignatureScheme {
1687 ED25519,
1688 Secp256k1,
1689 Secp256r1,
1690 BLS12381, MultiSig,
1692 ZkLoginAuthenticator,
1693 PasskeyAuthenticator,
1694}
1695
1696impl SignatureScheme {
1697 pub fn flag(&self) -> u8 {
1698 match self {
1699 SignatureScheme::ED25519 => 0x00,
1700 SignatureScheme::Secp256k1 => 0x01,
1701 SignatureScheme::Secp256r1 => 0x02,
1702 SignatureScheme::MultiSig => 0x03,
1703 SignatureScheme::BLS12381 => 0x04, SignatureScheme::ZkLoginAuthenticator => 0x05,
1706 SignatureScheme::PasskeyAuthenticator => 0x06,
1707 }
1708 }
1709
1710 pub fn update_hasher_with_flag(&self, hasher: &mut DefaultHash) {
1713 match self {
1714 SignatureScheme::ED25519 => (),
1715 _ => hasher.update([self.flag()]),
1716 };
1717 }
1718
1719 pub fn from_flag(flag: &str) -> Result<SignatureScheme, IotaError> {
1720 let byte_int = flag
1721 .parse::<u8>()
1722 .map_err(|_| IotaError::KeyConversion("Invalid key scheme".to_string()))?;
1723 Self::from_flag_byte(&byte_int)
1724 }
1725
1726 pub fn from_flag_byte(byte_int: &u8) -> Result<SignatureScheme, IotaError> {
1727 match byte_int {
1728 0x00 => Ok(SignatureScheme::ED25519),
1729 0x01 => Ok(SignatureScheme::Secp256k1),
1730 0x02 => Ok(SignatureScheme::Secp256r1),
1731 0x03 => Ok(SignatureScheme::MultiSig),
1732 0x04 => Ok(SignatureScheme::BLS12381),
1733 0x05 => Ok(SignatureScheme::ZkLoginAuthenticator),
1734 0x06 => Ok(SignatureScheme::PasskeyAuthenticator),
1735 _ => Err(IotaError::KeyConversion("Invalid key scheme".to_string())),
1736 }
1737 }
1738}
1739#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1742pub enum CompressedSignature {
1743 Ed25519(Ed25519SignatureAsBytes),
1744 Secp256k1(Secp256k1SignatureAsBytes),
1745 Secp256r1(Secp256r1SignatureAsBytes),
1746 ZkLogin(ZkLoginAuthenticatorAsBytes),
1747 Passkey(PasskeyAuthenticatorAsBytes),
1748}
1749
1750#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1751pub struct ZkLoginAuthenticatorAsBytes(#[schemars(with = "Base64")] pub Vec<u8>);
1752
1753#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
1754pub struct PasskeyAuthenticatorAsBytes(#[schemars(with = "Base64")] pub Vec<u8>);
1755
1756impl AsRef<[u8]> for CompressedSignature {
1757 fn as_ref(&self) -> &[u8] {
1758 match self {
1759 CompressedSignature::Ed25519(sig) => &sig.0,
1760 CompressedSignature::Secp256k1(sig) => &sig.0,
1761 CompressedSignature::Secp256r1(sig) => &sig.0,
1762 CompressedSignature::ZkLogin(sig) => &sig.0,
1763 CompressedSignature::Passkey(sig) => &sig.0,
1764 }
1765 }
1766}
1767
1768impl FromStr for Signature {
1769 type Err = eyre::Report;
1770 fn from_str(s: &str) -> Result<Self, Self::Err> {
1771 Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1772 }
1773}
1774
1775impl FromStr for PublicKey {
1776 type Err = eyre::Report;
1777 fn from_str(s: &str) -> Result<Self, Self::Err> {
1778 Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1779 }
1780}
1781
1782impl FromStr for GenericSignature {
1783 type Err = eyre::Report;
1784 fn from_str(s: &str) -> Result<Self, Self::Err> {
1785 Self::decode_base64(s).map_err(|e| eyre!("Fail to decode base64 {}", e.to_string()))
1786 }
1787}
1788
1789pub type RandomnessSignature = fastcrypto_tbls::types::Signature;
1792pub type RandomnessPartialSignature = fastcrypto_tbls::tbls::PartialSignature<RandomnessSignature>;
1793pub type RandomnessPrivateKey =
1794 fastcrypto_tbls::ecies_v1::PrivateKey<fastcrypto::groups::bls12381::G2Element>;
1795
1796#[derive(Clone, Copy, Hash, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
1798pub struct RandomnessRound(pub u64);
1799
1800impl Display for RandomnessRound {
1801 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1802 write!(f, "{}", self.0)
1803 }
1804}
1805
1806impl std::ops::Add for RandomnessRound {
1807 type Output = Self;
1808 fn add(self, other: Self) -> Self {
1809 Self(self.0 + other.0)
1810 }
1811}
1812
1813impl std::ops::Add<u64> for RandomnessRound {
1814 type Output = Self;
1815 fn add(self, other: u64) -> Self {
1816 Self(self.0 + other)
1817 }
1818}
1819
1820impl std::ops::Sub for RandomnessRound {
1821 type Output = Self;
1822 fn sub(self, other: Self) -> Self {
1823 Self(self.0 - other.0)
1824 }
1825}
1826
1827impl std::ops::Sub<u64> for RandomnessRound {
1828 type Output = Self;
1829 fn sub(self, other: u64) -> Self {
1830 Self(self.0 - other)
1831 }
1832}
1833
1834impl RandomnessRound {
1835 pub fn new(round: u64) -> Self {
1836 Self(round)
1837 }
1838
1839 pub fn checked_add(self, rhs: u64) -> Option<Self> {
1840 self.0.checked_add(rhs).map(Self)
1841 }
1842
1843 pub fn signature_message(&self) -> Vec<u8> {
1844 "random_beacon round "
1845 .as_bytes()
1846 .iter()
1847 .cloned()
1848 .chain(bcs::to_bytes(&self.0).expect("serialization should not fail"))
1849 .collect()
1850 }
1851}