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