sui_sdk_types/crypto/
multisig.rs

1use super::zklogin::ZkLoginAuthenticator;
2use super::zklogin::ZkLoginPublicIdentifier;
3use super::Ed25519PublicKey;
4use super::Ed25519Signature;
5use super::Secp256k1PublicKey;
6use super::Secp256k1Signature;
7use super::Secp256r1PublicKey;
8use super::Secp256r1Signature;
9use super::SignatureScheme;
10
11pub type WeightUnit = u8;
12pub type ThresholdUnit = u16;
13pub type BitmapUnit = u16;
14
15const MAX_COMMITTEE_SIZE: usize = 10;
16// TODO validate sigs
17// const MAX_BITMAP_VALUE: BitmapUnit = 0b1111111111;
18
19/// Enum of valid public keys for multisig committee members
20///
21/// # BCS
22///
23/// The BCS serialized form for this type is defined by the following ABNF:
24///
25/// ```text
26/// multisig-member-public-key = ed25519-multisig-member-public-key /
27///                              secp256k1-multisig-member-public-key /
28///                              secp256r1-multisig-member-public-key /
29///                              zklogin-multisig-member-public-key
30///
31/// ed25519-multisig-member-public-key   = %x00 ed25519-public-key
32/// secp256k1-multisig-member-public-key = %x01 secp256k1-public-key
33/// secp256r1-multisig-member-public-key = %x02 secp256r1-public-key
34/// zklogin-multisig-member-public-key   = %x03 zklogin-public-identifier
35/// ```
36///
37/// There is also a legacy encoding for this type defined as:
38///
39/// ```text
40/// legacy-multisig-member-public-key = string ; which is valid base64 encoded
41///                                            ; and the decoded bytes are defined
42///                                            ; by legacy-public-key
43/// legacy-public-key = (ed25519-flag ed25519-public-key) /
44///                     (secp256k1-flag secp256k1-public-key) /
45///                     (secp256r1-flag secp256r1-public-key)
46/// ```
47#[derive(Clone, Debug, PartialEq, Eq)]
48#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
49pub enum MultisigMemberPublicKey {
50    Ed25519(Ed25519PublicKey),
51    Secp256k1(Secp256k1PublicKey),
52    Secp256r1(Secp256r1PublicKey),
53    ZkLogin(ZkLoginPublicIdentifier),
54}
55
56/// A member in a multisig committee
57///
58/// # BCS
59///
60/// The BCS serialized form for this type is defined by the following ABNF:
61///
62/// ```text
63/// multisig-member = multisig-member-public-key
64///                   u8    ; weight
65/// ```
66///
67/// There is also a legacy encoding for this type defined as:
68///
69/// ```text
70/// legacy-multisig-member = legacy-multisig-member-public-key
71///                          u8     ; weight
72/// ```
73#[derive(Clone, Debug, PartialEq, Eq)]
74#[cfg_attr(
75    feature = "serde",
76    derive(serde_derive::Serialize, serde_derive::Deserialize)
77)]
78#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
79pub struct MultisigMember {
80    public_key: MultisigMemberPublicKey,
81    weight: WeightUnit,
82}
83
84impl MultisigMember {
85    /// Construct a new member from a `MultisigMemberPublicKey` and a `weight`.
86    pub fn new(public_key: MultisigMemberPublicKey, weight: WeightUnit) -> Self {
87        Self { public_key, weight }
88    }
89
90    /// This member's public key.
91    pub fn public_key(&self) -> &MultisigMemberPublicKey {
92        &self.public_key
93    }
94
95    /// Weight of this member's signature.
96    pub fn weight(&self) -> WeightUnit {
97        self.weight
98    }
99}
100
101/// A multisig committee
102///
103/// A `MultisigCommittee` is a set of members who collectively control a single `Address` on the
104/// Sui blockchain. The number of required signautres to authorize the execution of a transaction
105/// is determined by `(signature_0_weight + signature_1_weight ..) >= threshold`.
106///
107/// # BCS
108///
109/// The BCS serialized form for this type is defined by the following ABNF:
110///
111/// ```text
112/// multisig-committee = (vector multisig-member)
113///                      u16    ; threshold
114/// ```
115///
116/// There is also a legacy encoding for this type defined as:
117///
118/// ```text
119/// legacy-multisig-committee = (vector legacy-multisig-member)
120///                             u16     ; threshold
121/// ```
122#[derive(Debug, Clone, PartialEq, Eq)]
123#[cfg_attr(
124    feature = "serde",
125    derive(serde_derive::Serialize, serde_derive::Deserialize)
126)]
127#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
128pub struct MultisigCommittee {
129    /// A list of committee members and their corresponding weight.
130    #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=10).lift()))]
131    members: Vec<MultisigMember>,
132
133    /// If the total weight of the public keys corresponding to verified signatures is larger than
134    /// threshold, the Multisig is verified.
135    threshold: ThresholdUnit,
136}
137
138impl MultisigCommittee {
139    /// Construct a new committee from a list of `MultisigMember`s and a `threshold`.
140    ///
141    /// Note that the order of the members is significant towards deriving the `Address` governed
142    /// by this committee.
143    pub fn new(members: Vec<MultisigMember>, threshold: ThresholdUnit) -> Self {
144        Self { members, threshold }
145    }
146
147    /// The members of the committee
148    pub fn members(&self) -> &[MultisigMember] {
149        &self.members
150    }
151
152    /// The total signature weight required to authorize a transaction for the address
153    /// corresponding to this `MultisigCommittee`.
154    pub fn threshold(&self) -> ThresholdUnit {
155        self.threshold
156    }
157
158    /// Return the flag for this signature scheme
159    pub fn scheme(&self) -> SignatureScheme {
160        SignatureScheme::Multisig
161    }
162
163    /// Checks if the Committee is valid.
164    ///
165    /// A valid committee is one that:
166    ///  - Has a nonzero threshold
167    ///  - Has at least one member
168    ///  - Has at most ten members
169    ///  - No member has weight 0
170    ///  - the sum of the weights of all members must be larger than the threshold
171    ///  - contains no duplicate members
172    pub fn is_valid(&self) -> bool {
173        self.threshold != 0
174            && !self.members.is_empty()
175            && self.members.len() <= MAX_COMMITTEE_SIZE
176            && !self.members.iter().any(|member| member.weight == 0)
177            && self
178                .members
179                .iter()
180                .map(|member| member.weight as ThresholdUnit)
181                .sum::<ThresholdUnit>()
182                >= self.threshold
183            && !self.members.iter().enumerate().any(|(i, member)| {
184                self.members
185                    .iter()
186                    .skip(i + 1)
187                    .any(|m| member.public_key == m.public_key)
188            })
189    }
190}
191
192/// Aggregated signature from members of a multisig committee.
193///
194/// # BCS
195///
196/// The BCS serialized form for this type is defined by the following ABNF:
197///
198/// ```text
199/// multisig-aggregated-signature = (vector multisig-member-signature)
200///                                 u16     ; bitmap
201///                                 multisig-committee
202/// ```
203///
204/// There is also a legacy encoding for this type defined as:
205///
206/// ```text
207/// legacy-multisig-aggregated-signature = (vector multisig-member-signature)
208///                                        roaring-bitmap   ; bitmap
209///                                        legacy-multisig-committee
210/// roaring-bitmap = bytes  ; where the contents of the bytes are valid
211///                         ; according to the serialized spec for
212///                         ; roaring bitmaps
213/// ```
214///
215/// See [here](https://github.com/RoaringBitmap/RoaringFormatSpec) for the specification for the
216/// serialized format of RoaringBitmaps.
217#[derive(Debug, Clone)]
218#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
219pub struct MultisigAggregatedSignature {
220    /// The plain signature encoded with signature scheme.
221    ///
222    /// The signatures must be in the same order as they are listed in the committee.
223    #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=10).lift()))]
224    signatures: Vec<MultisigMemberSignature>,
225    /// A bitmap that indicates the position of which public key the signature should be
226    /// authenticated with.
227    bitmap: BitmapUnit,
228    /// Legacy encoding for the bitmap.
229    //TODO implement a strategy for legacy bitmap
230    #[cfg_attr(feature = "proptest", strategy(proptest::strategy::Just(None)))]
231    legacy_bitmap: Option<roaring::RoaringBitmap>,
232    /// The public key encoded with each public key with its signature scheme used along with the
233    /// corresponding weight.
234    committee: MultisigCommittee,
235}
236
237impl MultisigAggregatedSignature {
238    /// Construct a new aggregated multisig signature.
239    ///
240    /// Since the list of signatures doesn't contain sufficient information to identify which
241    /// committee member provided the signature, it is up to the caller to ensure that the provided
242    /// signature list is in the same order as it's corresponding member in the provided committee
243    /// and that it's position in the provided bitmap is set.
244    pub fn new(
245        committee: MultisigCommittee,
246        signatures: Vec<MultisigMemberSignature>,
247        bitmap: BitmapUnit,
248    ) -> Self {
249        Self {
250            signatures,
251            bitmap,
252            legacy_bitmap: None,
253            committee,
254        }
255    }
256
257    /// The list of signatures from committee members
258    pub fn signatures(&self) -> &[MultisigMemberSignature] {
259        &self.signatures
260    }
261
262    /// The bitmap that indicates which committee members provided their signature.
263    pub fn bitmap(&self) -> BitmapUnit {
264        self.bitmap
265    }
266
267    /// The legacy roaring bitmap, if this is a legacy formatted signature
268    pub fn legacy_bitmap(&self) -> Option<&roaring::RoaringBitmap> {
269        self.legacy_bitmap.as_ref()
270    }
271
272    /// Configure with a legacy roaring bitmap
273    pub fn with_legacy_bitmap(&mut self, legacy_bitmap: roaring::RoaringBitmap) {
274        self.legacy_bitmap = Some(legacy_bitmap);
275    }
276
277    /// The committee for this aggregated signature
278    pub fn committee(&self) -> &MultisigCommittee {
279        &self.committee
280    }
281}
282
283impl PartialEq for MultisigAggregatedSignature {
284    fn eq(&self, other: &Self) -> bool {
285        // Skip comparing the legacy bitmap since we always convert to the new bitmap form
286        self.bitmap == other.bitmap
287            && self.signatures == other.signatures
288            && self.committee == other.committee
289    }
290}
291
292impl Eq for MultisigAggregatedSignature {}
293
294/// Convert a roaring bitmap to plain bitmap.
295#[cfg(feature = "serde")]
296fn roaring_bitmap_to_u16(roaring: &roaring::RoaringBitmap) -> Result<BitmapUnit, &'static str> {
297    let mut val = 0;
298    for i in roaring.iter() {
299        if i >= MAX_COMMITTEE_SIZE as u32 {
300            return Err("invalid bitmap");
301        }
302        val |= 1 << i as u8;
303    }
304    Ok(val)
305}
306
307/// A signature from a member of a multisig committee.
308///
309/// # BCS
310///
311/// The BCS serialized form for this type is defined by the following ABNF:
312///
313/// ```text
314/// multisig-member-signature = ed25519-multisig-member-signature /
315///                             secp256k1-multisig-member-signature /
316///                             secp256r1-multisig-member-signature /
317///                             zklogin-multisig-member-signature
318///
319/// ed25519-multisig-member-signature   = %x00 ed25519-signature
320/// secp256k1-multisig-member-signature = %x01 secp256k1-signature
321/// secp256r1-multisig-member-signature = %x02 secp256r1-signature
322/// zklogin-multisig-member-signature   = %x03 zklogin-authenticator
323/// ```
324#[derive(Debug, Clone, PartialEq, Eq)]
325#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
326pub enum MultisigMemberSignature {
327    Ed25519(Ed25519Signature),
328    Secp256k1(Secp256k1Signature),
329    Secp256r1(Secp256r1Signature),
330    ZkLogin(Box<ZkLoginAuthenticator>),
331}
332
333#[cfg(feature = "serde")]
334#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
335mod serialization {
336    use super::*;
337    use crate::crypto::Base64Array33;
338    use crate::crypto::Base64Array34;
339    use crate::Ed25519PublicKey;
340    use crate::Secp256k1PublicKey;
341    use crate::Secp256r1PublicKey;
342    use crate::SignatureScheme;
343    use base64ct::Base64;
344    use base64ct::Encoding;
345    use serde::Deserialize;
346    use serde::Deserializer;
347    use serde::Serialize;
348    use serde::Serializer;
349    use serde_with::Bytes;
350    use serde_with::DeserializeAs;
351    use serde_with::SerializeAs;
352    use std::borrow::Cow;
353
354    pub struct Base64MultisigMemberPublicKey;
355
356    impl SerializeAs<MultisigMemberPublicKey> for Base64MultisigMemberPublicKey {
357        fn serialize_as<S>(
358            source: &MultisigMemberPublicKey,
359            serializer: S,
360        ) -> Result<S::Ok, S::Error>
361        where
362            S: Serializer,
363        {
364            match source {
365                MultisigMemberPublicKey::Ed25519(public_key) => {
366                    let mut buf = [0; 1 + Ed25519PublicKey::LENGTH];
367                    buf[0] = SignatureScheme::Ed25519 as u8;
368                    buf[1..].copy_from_slice(public_key.as_ref());
369                    Base64Array33::serialize_as(&buf, serializer)
370                }
371                MultisigMemberPublicKey::Secp256k1(public_key) => {
372                    let mut buf = [0; 1 + Secp256k1PublicKey::LENGTH];
373                    buf[0] = SignatureScheme::Secp256k1 as u8;
374                    buf[1..].copy_from_slice(public_key.as_ref());
375                    Base64Array34::serialize_as(&buf, serializer)
376                }
377                MultisigMemberPublicKey::Secp256r1(public_key) => {
378                    let mut buf = [0; 1 + Secp256r1PublicKey::LENGTH];
379                    buf[0] = SignatureScheme::Secp256r1 as u8;
380                    buf[1..].copy_from_slice(public_key.as_ref());
381                    Base64Array34::serialize_as(&buf, serializer)
382                }
383                MultisigMemberPublicKey::ZkLogin(_) => Err(serde::ser::Error::custom(
384                    "zklogin not supported in legacy multisig",
385                )),
386            }
387        }
388    }
389
390    impl<'de> DeserializeAs<'de, MultisigMemberPublicKey> for Base64MultisigMemberPublicKey {
391        fn deserialize_as<D>(deserializer: D) -> Result<MultisigMemberPublicKey, D::Error>
392        where
393            D: Deserializer<'de>,
394        {
395            let b64: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
396            let bytes = Base64::decode_vec(&b64).map_err(serde::de::Error::custom)?;
397            let flag = SignatureScheme::from_byte(
398                *bytes
399                    .first()
400                    .ok_or_else(|| serde::de::Error::custom("missing signature scheme falg"))?,
401            )
402            .map_err(serde::de::Error::custom)?;
403            let public_key_bytes = &bytes[1..];
404            match flag {
405                SignatureScheme::Ed25519 => {
406                    let public_key = Ed25519PublicKey::from_bytes(public_key_bytes)
407                        .map_err(serde::de::Error::custom)?;
408                    Ok(MultisigMemberPublicKey::Ed25519(public_key))
409                }
410                SignatureScheme::Secp256k1 => {
411                    let public_key = Secp256k1PublicKey::from_bytes(public_key_bytes)
412                        .map_err(serde::de::Error::custom)?;
413                    Ok(MultisigMemberPublicKey::Secp256k1(public_key))
414                }
415                SignatureScheme::Secp256r1 => {
416                    let public_key = Secp256r1PublicKey::from_bytes(public_key_bytes)
417                        .map_err(serde::de::Error::custom)?;
418                    Ok(MultisigMemberPublicKey::Secp256r1(public_key))
419                }
420                SignatureScheme::Multisig
421                | SignatureScheme::Bls12381
422                | SignatureScheme::ZkLogin
423                | SignatureScheme::Passkey => {
424                    Err(serde::de::Error::custom("invalid public key type"))
425                }
426            }
427        }
428    }
429
430    pub struct LegacyMultisigMember;
431
432    impl SerializeAs<MultisigMember> for LegacyMultisigMember {
433        fn serialize_as<S>(source: &MultisigMember, serializer: S) -> Result<S::Ok, S::Error>
434        where
435            S: Serializer,
436        {
437            #[derive(serde_derive::Serialize)]
438            struct LegacyMember<'a> {
439                #[serde(with = "::serde_with::As::<Base64MultisigMemberPublicKey>")]
440                public_key: &'a MultisigMemberPublicKey,
441                weight: WeightUnit,
442            }
443
444            let legacy = LegacyMember {
445                public_key: &source.public_key,
446                weight: source.weight,
447            };
448
449            legacy.serialize(serializer)
450        }
451    }
452
453    impl<'de> DeserializeAs<'de, MultisigMember> for LegacyMultisigMember {
454        fn deserialize_as<D>(deserializer: D) -> Result<MultisigMember, D::Error>
455        where
456            D: Deserializer<'de>,
457        {
458            #[derive(serde_derive::Deserialize)]
459            struct LegacyMember {
460                #[serde(with = "::serde_with::As::<Base64MultisigMemberPublicKey>")]
461                public_key: MultisigMemberPublicKey,
462                weight: WeightUnit,
463            }
464
465            let legacy = LegacyMember::deserialize(deserializer)?;
466
467            Ok(MultisigMember {
468                public_key: legacy.public_key,
469                weight: legacy.weight,
470            })
471        }
472    }
473
474    #[derive(serde_derive::Deserialize)]
475    pub struct Multisig {
476        signatures: Vec<MultisigMemberSignature>,
477        bitmap: BitmapUnit,
478        committee: MultisigCommittee,
479    }
480
481    #[derive(serde_derive::Serialize)]
482    pub struct MultisigRef<'a> {
483        signatures: &'a [MultisigMemberSignature],
484        bitmap: BitmapUnit,
485        committee: &'a MultisigCommittee,
486    }
487
488    #[derive(serde_derive::Deserialize)]
489    pub struct LegacyMultisig {
490        signatures: Vec<MultisigMemberSignature>,
491        #[serde(with = "::serde_with::As::<crate::_serde::BinaryRoaringBitmap>")]
492        bitmap: roaring::RoaringBitmap,
493        committee: LegacyMultisigCommittee,
494    }
495
496    #[derive(serde_derive::Serialize)]
497    pub struct LegacyMultisigRef<'a> {
498        signatures: &'a [MultisigMemberSignature],
499        #[serde(with = "::serde_with::As::<crate::_serde::BinaryRoaringBitmap>")]
500        bitmap: &'a roaring::RoaringBitmap,
501        committee: LegacyMultisigCommitteeRef<'a>,
502    }
503
504    #[derive(serde_derive::Deserialize)]
505    struct LegacyMultisigCommittee {
506        #[serde(with = "::serde_with::As::<Vec<LegacyMultisigMember>>")]
507        members: Vec<MultisigMember>,
508        threshold: ThresholdUnit,
509    }
510
511    #[derive(serde_derive::Serialize)]
512    struct LegacyMultisigCommitteeRef<'a> {
513        #[serde(with = "::serde_with::As::<&[LegacyMultisigMember]>")]
514        members: &'a [MultisigMember],
515        threshold: ThresholdUnit,
516    }
517
518    #[derive(serde_derive::Deserialize)]
519    struct ReadableMultisigAggregatedSignature {
520        signatures: Vec<MultisigMemberSignature>,
521        bitmap: BitmapUnit,
522        #[serde(default)]
523        #[serde(with = "::serde_with::As::<Option<crate::_serde::Base64RoaringBitmap>>")]
524        legacy_bitmap: Option<roaring::RoaringBitmap>,
525        committee: MultisigCommittee,
526    }
527
528    #[derive(serde_derive::Serialize)]
529    struct ReadableMultisigAggregatedSignatureRef<'a> {
530        signatures: &'a [MultisigMemberSignature],
531        bitmap: BitmapUnit,
532        #[serde(skip_serializing_if = "Option::is_none")]
533        #[serde(with = "::serde_with::As::<Option<crate::_serde::Base64RoaringBitmap>>")]
534        legacy_bitmap: &'a Option<roaring::RoaringBitmap>,
535        committee: &'a MultisigCommittee,
536    }
537
538    impl Serialize for MultisigAggregatedSignature {
539        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
540        where
541            S: Serializer,
542        {
543            if serializer.is_human_readable() {
544                let readable = ReadableMultisigAggregatedSignatureRef {
545                    signatures: &self.signatures,
546                    bitmap: self.bitmap,
547                    legacy_bitmap: &self.legacy_bitmap,
548                    committee: &self.committee,
549                };
550                readable.serialize(serializer)
551            } else {
552                let bytes = self.to_bytes();
553                serializer.serialize_bytes(&bytes)
554            }
555        }
556    }
557
558    impl<'de> Deserialize<'de> for MultisigAggregatedSignature {
559        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
560        where
561            D: Deserializer<'de>,
562        {
563            if deserializer.is_human_readable() {
564                let readable = ReadableMultisigAggregatedSignature::deserialize(deserializer)?;
565                Ok(Self {
566                    signatures: readable.signatures,
567                    bitmap: readable.bitmap,
568                    legacy_bitmap: readable.legacy_bitmap,
569                    committee: readable.committee,
570                })
571            } else {
572                let bytes: Cow<'de, [u8]> = Bytes::deserialize_as(deserializer)?;
573                Self::from_serialized_bytes(bytes)
574            }
575        }
576    }
577
578    impl MultisigAggregatedSignature {
579        pub(crate) fn to_bytes(&self) -> Vec<u8> {
580            let mut buf = Vec::new();
581            buf.push(SignatureScheme::Multisig as u8);
582
583            if let Some(bitmap) = &self.legacy_bitmap {
584                let legacy = LegacyMultisigRef {
585                    signatures: &self.signatures,
586                    bitmap,
587                    committee: LegacyMultisigCommitteeRef {
588                        members: &self.committee.members,
589                        threshold: self.committee.threshold,
590                    },
591                };
592
593                bcs::serialize_into(&mut buf, &legacy).expect("serialization cannot fail");
594            } else {
595                let multisig = MultisigRef {
596                    signatures: &self.signatures,
597                    bitmap: self.bitmap,
598                    committee: &self.committee,
599                };
600                bcs::serialize_into(&mut buf, &multisig).expect("serialization cannot fail");
601            }
602            buf
603        }
604
605        pub(crate) fn from_serialized_bytes<T: AsRef<[u8]>, E: serde::de::Error>(
606            bytes: T,
607        ) -> Result<Self, E> {
608            let bytes = bytes.as_ref();
609            let flag = SignatureScheme::from_byte(
610                *bytes
611                    .first()
612                    .ok_or_else(|| serde::de::Error::custom("missing signature scheme falg"))?,
613            )
614            .map_err(serde::de::Error::custom)?;
615            if flag != SignatureScheme::Multisig {
616                return Err(serde::de::Error::custom("invalid multisig flag"));
617            }
618            let bcs_bytes = &bytes[1..];
619
620            // Unfortunately we have no information in the serialized form of a Multisig to be
621            // able to determine if its a Legacy format or the new standard format so we just
622            // need to try each.
623            //
624            // We'll start with the newer format as that should be more prevalent.
625            if let Ok(multisig) = bcs::from_bytes::<Multisig>(bcs_bytes) {
626                Ok(Self {
627                    signatures: multisig.signatures,
628                    bitmap: multisig.bitmap,
629                    legacy_bitmap: None,
630                    committee: multisig.committee,
631                })
632            } else if let Ok(legacy) = bcs::from_bytes::<LegacyMultisig>(bcs_bytes) {
633                Ok(Self {
634                    signatures: legacy.signatures,
635                    bitmap: roaring_bitmap_to_u16(&legacy.bitmap)
636                        .map_err(serde::de::Error::custom)?,
637                    legacy_bitmap: Some(legacy.bitmap),
638                    committee: MultisigCommittee {
639                        members: legacy.committee.members,
640                        threshold: legacy.committee.threshold,
641                    },
642                })
643            } else {
644                Err(serde::de::Error::custom("invalid multisig"))
645            }
646        }
647    }
648
649    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
650    enum MemberPublicKey {
651        Ed25519(Ed25519PublicKey),
652        Secp256k1(Secp256k1PublicKey),
653        Secp256r1(Secp256r1PublicKey),
654        ZkLogin(ZkLoginPublicIdentifier),
655    }
656
657    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
658    #[serde(tag = "scheme", rename_all = "lowercase")]
659    #[serde(rename = "MultisigMemberPublicKey")]
660    enum ReadableMemberPublicKey {
661        Ed25519 { public_key: Ed25519PublicKey },
662        Secp256k1 { public_key: Secp256k1PublicKey },
663        Secp256r1 { public_key: Secp256r1PublicKey },
664        ZkLogin(ZkLoginPublicIdentifier),
665    }
666
667    impl Serialize for MultisigMemberPublicKey {
668        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
669        where
670            S: Serializer,
671        {
672            if serializer.is_human_readable() {
673                let readable = match self {
674                    MultisigMemberPublicKey::Ed25519(public_key) => {
675                        ReadableMemberPublicKey::Ed25519 {
676                            public_key: *public_key,
677                        }
678                    }
679                    MultisigMemberPublicKey::Secp256k1(public_key) => {
680                        ReadableMemberPublicKey::Secp256k1 {
681                            public_key: *public_key,
682                        }
683                    }
684                    MultisigMemberPublicKey::Secp256r1(public_key) => {
685                        ReadableMemberPublicKey::Secp256r1 {
686                            public_key: *public_key,
687                        }
688                    }
689                    MultisigMemberPublicKey::ZkLogin(public_id) => {
690                        ReadableMemberPublicKey::ZkLogin(public_id.clone())
691                    }
692                };
693                readable.serialize(serializer)
694            } else {
695                let binary = match self {
696                    MultisigMemberPublicKey::Ed25519(public_key) => {
697                        MemberPublicKey::Ed25519(*public_key)
698                    }
699                    MultisigMemberPublicKey::Secp256k1(public_key) => {
700                        MemberPublicKey::Secp256k1(*public_key)
701                    }
702                    MultisigMemberPublicKey::Secp256r1(public_key) => {
703                        MemberPublicKey::Secp256r1(*public_key)
704                    }
705                    MultisigMemberPublicKey::ZkLogin(public_id) => {
706                        MemberPublicKey::ZkLogin(public_id.clone())
707                    }
708                };
709                binary.serialize(serializer)
710            }
711        }
712    }
713
714    impl<'de> Deserialize<'de> for MultisigMemberPublicKey {
715        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
716        where
717            D: Deserializer<'de>,
718        {
719            if deserializer.is_human_readable() {
720                let readable = ReadableMemberPublicKey::deserialize(deserializer)?;
721                Ok(match readable {
722                    ReadableMemberPublicKey::Ed25519 { public_key } => Self::Ed25519(public_key),
723                    ReadableMemberPublicKey::Secp256k1 { public_key } => {
724                        Self::Secp256k1(public_key)
725                    }
726                    ReadableMemberPublicKey::Secp256r1 { public_key } => {
727                        Self::Secp256r1(public_key)
728                    }
729                    ReadableMemberPublicKey::ZkLogin(public_id) => Self::ZkLogin(public_id),
730                })
731            } else {
732                let binary = MemberPublicKey::deserialize(deserializer)?;
733                Ok(match binary {
734                    MemberPublicKey::Ed25519(public_key) => Self::Ed25519(public_key),
735                    MemberPublicKey::Secp256k1(public_key) => Self::Secp256k1(public_key),
736                    MemberPublicKey::Secp256r1(public_key) => Self::Secp256r1(public_key),
737                    MemberPublicKey::ZkLogin(public_id) => Self::ZkLogin(public_id),
738                })
739            }
740        }
741    }
742
743    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
744    enum MemberSignature {
745        Ed25519(Ed25519Signature),
746        Secp256k1(Secp256k1Signature),
747        Secp256r1(Secp256r1Signature),
748        ZkLogin(Box<ZkLoginAuthenticator>),
749    }
750
751    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
752    #[serde(tag = "scheme", rename_all = "lowercase")]
753    #[serde(rename = "MultisigMemberSignature")]
754    enum ReadableMemberSignature {
755        Ed25519 { signature: Ed25519Signature },
756        Secp256k1 { signature: Secp256k1Signature },
757        Secp256r1 { signature: Secp256r1Signature },
758        ZkLogin(Box<ZkLoginAuthenticator>),
759    }
760
761    impl Serialize for MultisigMemberSignature {
762        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
763        where
764            S: Serializer,
765        {
766            if serializer.is_human_readable() {
767                let readable = match self {
768                    MultisigMemberSignature::Ed25519(signature) => {
769                        ReadableMemberSignature::Ed25519 {
770                            signature: *signature,
771                        }
772                    }
773                    MultisigMemberSignature::Secp256k1(signature) => {
774                        ReadableMemberSignature::Secp256k1 {
775                            signature: *signature,
776                        }
777                    }
778                    MultisigMemberSignature::Secp256r1(signature) => {
779                        ReadableMemberSignature::Secp256r1 {
780                            signature: *signature,
781                        }
782                    }
783                    MultisigMemberSignature::ZkLogin(authenticator) => {
784                        ReadableMemberSignature::ZkLogin(authenticator.clone())
785                    }
786                };
787                readable.serialize(serializer)
788            } else {
789                let binary = match self {
790                    MultisigMemberSignature::Ed25519(signature) => {
791                        MemberSignature::Ed25519(*signature)
792                    }
793                    MultisigMemberSignature::Secp256k1(signature) => {
794                        MemberSignature::Secp256k1(*signature)
795                    }
796                    MultisigMemberSignature::Secp256r1(signature) => {
797                        MemberSignature::Secp256r1(*signature)
798                    }
799                    MultisigMemberSignature::ZkLogin(authenticator) => {
800                        MemberSignature::ZkLogin(authenticator.clone())
801                    }
802                };
803                binary.serialize(serializer)
804            }
805        }
806    }
807
808    impl<'de> Deserialize<'de> for MultisigMemberSignature {
809        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
810        where
811            D: Deserializer<'de>,
812        {
813            if deserializer.is_human_readable() {
814                let readable = ReadableMemberSignature::deserialize(deserializer)?;
815                Ok(match readable {
816                    ReadableMemberSignature::Ed25519 { signature } => Self::Ed25519(signature),
817                    ReadableMemberSignature::Secp256k1 { signature } => Self::Secp256k1(signature),
818                    ReadableMemberSignature::Secp256r1 { signature } => Self::Secp256r1(signature),
819                    ReadableMemberSignature::ZkLogin(authenticator) => Self::ZkLogin(authenticator),
820                })
821            } else {
822                let binary = MemberSignature::deserialize(deserializer)?;
823                Ok(match binary {
824                    MemberSignature::Ed25519(signature) => Self::Ed25519(signature),
825                    MemberSignature::Secp256k1(signature) => Self::Secp256k1(signature),
826                    MemberSignature::Secp256r1(signature) => Self::Secp256r1(signature),
827                    MemberSignature::ZkLogin(authenticator) => Self::ZkLogin(authenticator),
828                })
829            }
830        }
831    }
832}