sui_sdk_types/crypto/
multisig.rs

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