sui_sdk_types/crypto/
signature.rs

1use super::Ed25519PublicKey;
2use super::Ed25519Signature;
3use super::MultisigAggregatedSignature;
4use super::PasskeyAuthenticator;
5use super::Secp256k1PublicKey;
6use super::Secp256k1Signature;
7use super::Secp256r1PublicKey;
8use super::Secp256r1Signature;
9use super::ZkLoginAuthenticator;
10
11/// A basic signature
12///
13/// This enumeration defines the set of simple or basic signature schemes supported by Sui. Most
14/// signature schemes supported by Sui end up comprising of a at least one simple signature scheme.
15///
16/// # BCS
17///
18/// The BCS serialized form for this type is defined by the following ABNF:
19///
20/// ```text
21/// simple-signature-bcs = bytes ; where the contents of the bytes are defined by <simple-signature>
22/// simple-signature = (ed25519-flag ed25519-signature ed25519-public-key) /
23///                    (secp256k1-flag secp256k1-signature secp256k1-public-key) /
24///                    (secp256r1-flag secp256r1-signature secp256r1-public-key)
25/// ```
26///
27/// Note: Due to historical reasons, signatures are serialized slightly different from the majority
28/// of the types in Sui. In particular if a signature is ever embedded in another structure it
29/// generally is serialized as `bytes` meaning it has a length prefix that defines the length of
30/// the completely serialized signature.
31#[derive(Clone, Debug, PartialEq, Eq, Hash)]
32#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
33#[non_exhaustive]
34pub enum SimpleSignature {
35    Ed25519 {
36        signature: Ed25519Signature,
37        public_key: Ed25519PublicKey,
38    },
39    Secp256k1 {
40        signature: Secp256k1Signature,
41        public_key: Secp256k1PublicKey,
42    },
43    Secp256r1 {
44        signature: Secp256r1Signature,
45        public_key: Secp256r1PublicKey,
46    },
47}
48
49impl SimpleSignature {
50    /// Return the flag for this signature scheme
51    pub fn scheme(&self) -> SignatureScheme {
52        match self {
53            SimpleSignature::Ed25519 { .. } => SignatureScheme::Ed25519,
54            SimpleSignature::Secp256k1 { .. } => SignatureScheme::Secp256k1,
55            SimpleSignature::Secp256r1 { .. } => SignatureScheme::Secp256r1,
56        }
57    }
58}
59
60impl SimpleSignature {
61    #[cfg(feature = "serde")]
62    #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
63    fn to_bytes(&self) -> Vec<u8> {
64        let mut buf = Vec::new();
65        match self {
66            SimpleSignature::Ed25519 {
67                signature,
68                public_key,
69            } => {
70                buf.push(SignatureScheme::Ed25519 as u8);
71                buf.extend_from_slice(signature.as_ref());
72                buf.extend_from_slice(public_key.as_ref());
73            }
74            SimpleSignature::Secp256k1 {
75                signature,
76                public_key,
77            } => {
78                buf.push(SignatureScheme::Secp256k1 as u8);
79                buf.extend_from_slice(signature.as_ref());
80                buf.extend_from_slice(public_key.as_ref());
81            }
82            SimpleSignature::Secp256r1 {
83                signature,
84                public_key,
85            } => {
86                buf.push(SignatureScheme::Secp256r1 as u8);
87                buf.extend_from_slice(signature.as_ref());
88                buf.extend_from_slice(public_key.as_ref());
89            }
90        }
91
92        buf
93    }
94
95    #[cfg(feature = "serde")]
96    #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
97    fn from_serialized_bytes<T: AsRef<[u8]>, E: serde::de::Error>(bytes: T) -> Result<Self, E> {
98        let bytes = bytes.as_ref();
99        let flag = SignatureScheme::from_byte(
100            *bytes
101                .first()
102                .ok_or_else(|| serde::de::Error::custom("missing signature scheme flag"))?,
103        )
104        .map_err(serde::de::Error::custom)?;
105        match flag {
106            SignatureScheme::Ed25519 => {
107                let expected_length = 1 + Ed25519Signature::LENGTH + Ed25519PublicKey::LENGTH;
108
109                if bytes.len() != expected_length {
110                    return Err(serde::de::Error::custom("invalid ed25519 signature"));
111                }
112
113                let mut signature = [0; Ed25519Signature::LENGTH];
114                signature.copy_from_slice(&bytes[1..(1 + Ed25519Signature::LENGTH)]);
115
116                let mut public_key = [0; Ed25519PublicKey::LENGTH];
117                public_key.copy_from_slice(&bytes[(1 + Ed25519Signature::LENGTH)..]);
118
119                Ok(SimpleSignature::Ed25519 {
120                    signature: Ed25519Signature::new(signature),
121                    public_key: Ed25519PublicKey::new(public_key),
122                })
123            }
124            SignatureScheme::Secp256k1 => {
125                let expected_length = 1 + Secp256k1Signature::LENGTH + Secp256k1PublicKey::LENGTH;
126
127                if bytes.len() != expected_length {
128                    return Err(serde::de::Error::custom("invalid secp25k1 signature"));
129                }
130
131                let mut signature = [0; Secp256k1Signature::LENGTH];
132                signature.copy_from_slice(&bytes[1..(1 + Secp256k1Signature::LENGTH)]);
133
134                let mut public_key = [0; Secp256k1PublicKey::LENGTH];
135                public_key.copy_from_slice(&bytes[(1 + Secp256k1Signature::LENGTH)..]);
136
137                Ok(SimpleSignature::Secp256k1 {
138                    signature: Secp256k1Signature::new(signature),
139                    public_key: Secp256k1PublicKey::new(public_key),
140                })
141            }
142            SignatureScheme::Secp256r1 => {
143                let expected_length = 1 + Secp256r1Signature::LENGTH + Secp256r1PublicKey::LENGTH;
144
145                if bytes.len() != expected_length {
146                    return Err(serde::de::Error::custom("invalid secp25r1 signature"));
147                }
148
149                let mut signature = [0; Secp256r1Signature::LENGTH];
150                signature.copy_from_slice(&bytes[1..(1 + Secp256r1Signature::LENGTH)]);
151
152                let mut public_key = [0; Secp256r1PublicKey::LENGTH];
153                public_key.copy_from_slice(&bytes[(1 + Secp256r1Signature::LENGTH)..]);
154
155                Ok(SimpleSignature::Secp256r1 {
156                    signature: Secp256r1Signature::new(signature),
157                    public_key: Secp256r1PublicKey::new(public_key),
158                })
159            }
160            SignatureScheme::Multisig
161            | SignatureScheme::Bls12381
162            | SignatureScheme::ZkLogin
163            | SignatureScheme::Passkey => Err(serde::de::Error::custom("invalid signature scheme")),
164        }
165    }
166}
167
168#[cfg(feature = "serde")]
169#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
170impl serde::Serialize for SimpleSignature {
171    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
172    where
173        S: serde::Serializer,
174    {
175        #[derive(serde_derive::Serialize)]
176        #[serde(tag = "scheme")]
177        #[serde(rename_all = "lowercase")]
178        enum Sig<'a> {
179            Ed25519 {
180                signature: &'a Ed25519Signature,
181                public_key: &'a Ed25519PublicKey,
182            },
183            Secp256k1 {
184                signature: &'a Secp256k1Signature,
185                public_key: &'a Secp256k1PublicKey,
186            },
187            Secp256r1 {
188                signature: &'a Secp256r1Signature,
189                public_key: &'a Secp256r1PublicKey,
190            },
191        }
192
193        if serializer.is_human_readable() {
194            let sig = match self {
195                SimpleSignature::Ed25519 {
196                    signature,
197                    public_key,
198                } => Sig::Ed25519 {
199                    signature,
200                    public_key,
201                },
202                SimpleSignature::Secp256k1 {
203                    signature,
204                    public_key,
205                } => Sig::Secp256k1 {
206                    signature,
207                    public_key,
208                },
209                SimpleSignature::Secp256r1 {
210                    signature,
211                    public_key,
212                } => Sig::Secp256r1 {
213                    signature,
214                    public_key,
215                },
216            };
217
218            sig.serialize(serializer)
219        } else {
220            match self {
221                SimpleSignature::Ed25519 {
222                    signature,
223                    public_key,
224                } => {
225                    let mut buf = [0; 1 + Ed25519Signature::LENGTH + Ed25519PublicKey::LENGTH];
226                    buf[0] = SignatureScheme::Ed25519 as u8;
227                    buf[1..(1 + Ed25519Signature::LENGTH)].copy_from_slice(signature.as_ref());
228                    buf[(1 + Ed25519Signature::LENGTH)..].copy_from_slice(public_key.as_ref());
229
230                    serializer.serialize_bytes(&buf)
231                }
232                SimpleSignature::Secp256k1 {
233                    signature,
234                    public_key,
235                } => {
236                    let mut buf = [0; 1 + Secp256k1Signature::LENGTH + Secp256k1PublicKey::LENGTH];
237                    buf[0] = SignatureScheme::Secp256k1 as u8;
238                    buf[1..(1 + Secp256k1Signature::LENGTH)].copy_from_slice(signature.as_ref());
239                    buf[(1 + Secp256k1Signature::LENGTH)..].copy_from_slice(public_key.as_ref());
240
241                    serializer.serialize_bytes(&buf)
242                }
243                SimpleSignature::Secp256r1 {
244                    signature,
245                    public_key,
246                } => {
247                    let mut buf = [0; 1 + Secp256r1Signature::LENGTH + Secp256r1PublicKey::LENGTH];
248                    buf[0] = SignatureScheme::Secp256r1 as u8;
249                    buf[1..(1 + Secp256r1Signature::LENGTH)].copy_from_slice(signature.as_ref());
250                    buf[(1 + Secp256r1Signature::LENGTH)..].copy_from_slice(public_key.as_ref());
251
252                    serializer.serialize_bytes(&buf)
253                }
254            }
255        }
256    }
257}
258
259#[cfg(feature = "serde")]
260#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
261impl<'de> serde::Deserialize<'de> for SimpleSignature {
262    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
263    where
264        D: serde::Deserializer<'de>,
265    {
266        #[derive(serde_derive::Deserialize)]
267        #[serde(tag = "scheme")]
268        #[serde(rename_all = "lowercase")]
269        enum Sig {
270            Ed25519 {
271                signature: Ed25519Signature,
272                public_key: Ed25519PublicKey,
273            },
274            Secp256k1 {
275                signature: Secp256k1Signature,
276                public_key: Secp256k1PublicKey,
277            },
278            Secp256r1 {
279                signature: Secp256r1Signature,
280                public_key: Secp256r1PublicKey,
281            },
282        }
283
284        if deserializer.is_human_readable() {
285            let sig = Sig::deserialize(deserializer)?;
286            Ok(match sig {
287                Sig::Ed25519 {
288                    signature,
289                    public_key,
290                } => SimpleSignature::Ed25519 {
291                    signature,
292                    public_key,
293                },
294                Sig::Secp256k1 {
295                    signature,
296                    public_key,
297                } => SimpleSignature::Secp256k1 {
298                    signature,
299                    public_key,
300                },
301                Sig::Secp256r1 {
302                    signature,
303                    public_key,
304                } => SimpleSignature::Secp256r1 {
305                    signature,
306                    public_key,
307                },
308            })
309        } else {
310            let bytes: std::borrow::Cow<'de, [u8]> = std::borrow::Cow::deserialize(deserializer)?;
311            Self::from_serialized_bytes(bytes)
312        }
313    }
314}
315
316/// Flag use to disambiguate the signature schemes supported by Sui.
317///
318/// # BCS
319///
320/// The BCS serialized form for this type is defined by the following ABNF:
321///
322/// ```text
323/// signature-scheme = ed25519-flag / secp256k1-flag / secp256r1-flag /
324///                    multisig-flag / bls-flag / zklogin-flag / passkey-flag
325/// ed25519-flag     = %x00
326/// secp256k1-flag   = %x01
327/// secp256r1-flag   = %x02
328/// multisig-flag    = %x03
329/// bls-flag         = %x04
330/// zklogin-flag     = %x05
331/// passkey-flag     = %x06
332/// ```
333#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
334#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
335#[non_exhaustive]
336#[repr(u8)]
337pub enum SignatureScheme {
338    Ed25519 = 0x00,
339    Secp256k1 = 0x01,
340    Secp256r1 = 0x02,
341    Multisig = 0x03,
342    Bls12381 = 0x04, // This is currently not supported for user addresses
343    ZkLogin = 0x05,
344    Passkey = 0x06,
345}
346
347impl SignatureScheme {
348    /// Return the name of this signature scheme
349    pub fn name(self) -> &'static str {
350        match self {
351            SignatureScheme::Ed25519 => "ed25519",
352            SignatureScheme::Secp256k1 => "secp256k1",
353            SignatureScheme::Secp256r1 => "secp256r1",
354            SignatureScheme::Multisig => "multisig",
355            SignatureScheme::Bls12381 => "bls12381",
356            SignatureScheme::ZkLogin => "zklogin",
357            SignatureScheme::Passkey => "passkey",
358        }
359    }
360
361    /// Try constructing from a byte flag
362    pub fn from_byte(flag: u8) -> Result<Self, InvalidSignatureScheme> {
363        match flag {
364            0x00 => Ok(Self::Ed25519),
365            0x01 => Ok(Self::Secp256k1),
366            0x02 => Ok(Self::Secp256r1),
367            0x03 => Ok(Self::Multisig),
368            0x04 => Ok(Self::Bls12381),
369            0x05 => Ok(Self::ZkLogin),
370            0x06 => Ok(Self::Passkey),
371            invalid => Err(InvalidSignatureScheme(invalid)),
372        }
373    }
374
375    /// Convert to a byte flag
376    pub fn to_u8(self) -> u8 {
377        self as u8
378    }
379}
380
381impl Ed25519PublicKey {
382    /// Return the flag for this signature scheme
383    pub fn scheme(&self) -> SignatureScheme {
384        SignatureScheme::Ed25519
385    }
386}
387
388impl Secp256k1PublicKey {
389    /// Return the flag for this signature scheme
390    pub fn scheme(&self) -> SignatureScheme {
391        SignatureScheme::Secp256k1
392    }
393}
394
395impl Secp256r1PublicKey {
396    /// Return the flag for this signature scheme
397    pub fn scheme(&self) -> SignatureScheme {
398        SignatureScheme::Secp256r1
399    }
400}
401
402impl super::ZkLoginPublicIdentifier {
403    /// Return the flag for this signature scheme
404    pub fn scheme(&self) -> SignatureScheme {
405        SignatureScheme::ZkLogin
406    }
407}
408
409impl super::PasskeyPublicKey {
410    /// Return the flag for this signature scheme
411    pub fn scheme(&self) -> SignatureScheme {
412        SignatureScheme::Passkey
413    }
414}
415
416#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
417pub struct InvalidSignatureScheme(u8);
418
419impl std::fmt::Display for InvalidSignatureScheme {
420    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421        write!(f, "invalid signature scheme: {:02x}", self.0)
422    }
423}
424
425/// A signature from a user
426///
427/// A `UserSignature` is most commonly used to authorize the execution and inclusion of a
428/// transaction to the blockchain.
429///
430/// # BCS
431///
432/// The BCS serialized form for this type is defined by the following ABNF:
433///
434/// ```text
435/// user-signature-bcs = bytes ; where the contents of the bytes are defined by <user-signature>
436/// user-signature = simple-signature / multisig / multisig-legacy / zklogin / passkey
437/// ```
438///
439/// Note: Due to historical reasons, signatures are serialized slightly different from the majority
440/// of the types in Sui. In particular if a signature is ever embedded in another structure it
441/// generally is serialized as `bytes` meaning it has a length prefix that defines the length of
442/// the completely serialized signature.
443#[derive(Clone, Debug, PartialEq, Eq)]
444#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
445#[non_exhaustive]
446pub enum UserSignature {
447    Simple(SimpleSignature),
448    Multisig(MultisigAggregatedSignature),
449    ZkLogin(Box<ZkLoginAuthenticator>),
450    Passkey(PasskeyAuthenticator),
451}
452
453impl UserSignature {
454    /// Return the flag for this signature scheme
455    pub fn scheme(&self) -> SignatureScheme {
456        match self {
457            UserSignature::Simple(simple) => simple.scheme(),
458            UserSignature::Multisig(_) => SignatureScheme::Multisig,
459            UserSignature::ZkLogin(_) => SignatureScheme::ZkLogin,
460            UserSignature::Passkey(_) => SignatureScheme::Passkey,
461        }
462    }
463}
464
465#[cfg(feature = "serde")]
466#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
467mod serialization {
468    use super::*;
469
470    impl UserSignature {
471        pub fn to_bytes(&self) -> Vec<u8> {
472            match self {
473                UserSignature::Simple(s) => s.to_bytes(),
474                UserSignature::Multisig(m) => m.to_bytes(),
475                UserSignature::ZkLogin(z) => z.to_bytes(),
476                UserSignature::Passkey(p) => p.to_bytes(),
477            }
478        }
479
480        pub fn to_base64(&self) -> String {
481            use base64ct::Encoding;
482
483            base64ct::Base64::encode_string(&self.to_bytes())
484        }
485
486        fn from_serialized_bytes<T: AsRef<[u8]>, E: serde::de::Error>(bytes: T) -> Result<Self, E> {
487            let bytes = bytes.as_ref();
488
489            let flag = SignatureScheme::from_byte(
490                *bytes
491                    .first()
492                    .ok_or_else(|| serde::de::Error::custom("missing signature scheme flag"))?,
493            )
494            .map_err(serde::de::Error::custom)?;
495            match flag {
496                SignatureScheme::Ed25519
497                | SignatureScheme::Secp256k1
498                | SignatureScheme::Secp256r1 => {
499                    let simple = SimpleSignature::from_serialized_bytes(bytes)?;
500                    Ok(Self::Simple(simple))
501                }
502                SignatureScheme::Multisig => {
503                    let multisig = MultisigAggregatedSignature::from_serialized_bytes(bytes)?;
504                    Ok(Self::Multisig(multisig))
505                }
506                SignatureScheme::Bls12381 => Err(serde::de::Error::custom(
507                    "bls not supported for user signatures",
508                )),
509                SignatureScheme::ZkLogin => {
510                    let zklogin = ZkLoginAuthenticator::from_serialized_bytes(bytes)?;
511                    Ok(Self::ZkLogin(Box::new(zklogin)))
512                }
513                SignatureScheme::Passkey => {
514                    let passkey = PasskeyAuthenticator::from_serialized_bytes(bytes)?;
515                    Ok(Self::Passkey(passkey))
516                }
517            }
518        }
519
520        pub fn from_bytes(bytes: &[u8]) -> Result<Self, bcs::Error> {
521            Self::from_serialized_bytes(bytes)
522        }
523
524        pub fn from_base64(s: &str) -> Result<Self, bcs::Error> {
525            use base64ct::Encoding;
526            use serde::de::Error;
527
528            let bytes = base64ct::Base64::decode_vec(s).map_err(bcs::Error::custom)?;
529            Self::from_bytes(&bytes)
530        }
531    }
532
533    #[derive(serde_derive::Serialize)]
534    #[serde(tag = "scheme", rename_all = "lowercase")]
535    enum ReadableUserSignatureRef<'a> {
536        Ed25519 {
537            signature: &'a Ed25519Signature,
538            public_key: &'a Ed25519PublicKey,
539        },
540        Secp256k1 {
541            signature: &'a Secp256k1Signature,
542            public_key: &'a Secp256k1PublicKey,
543        },
544        Secp256r1 {
545            signature: &'a Secp256r1Signature,
546            public_key: &'a Secp256r1PublicKey,
547        },
548        Multisig(&'a MultisigAggregatedSignature),
549        ZkLogin(&'a ZkLoginAuthenticator),
550        Passkey(&'a PasskeyAuthenticator),
551    }
552
553    #[derive(serde_derive::Deserialize)]
554    #[serde(tag = "scheme", rename_all = "lowercase")]
555    #[serde(rename = "UserSignature")]
556    enum ReadableUserSignature {
557        Ed25519 {
558            signature: Ed25519Signature,
559            public_key: Ed25519PublicKey,
560        },
561        Secp256k1 {
562            signature: Secp256k1Signature,
563            public_key: Secp256k1PublicKey,
564        },
565        Secp256r1 {
566            signature: Secp256r1Signature,
567            public_key: Secp256r1PublicKey,
568        },
569        Multisig(MultisigAggregatedSignature),
570        ZkLogin(Box<ZkLoginAuthenticator>),
571        Passkey(PasskeyAuthenticator),
572    }
573
574    impl serde::Serialize for UserSignature {
575        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
576        where
577            S: serde::Serializer,
578        {
579            if serializer.is_human_readable() {
580                let readable = match self {
581                    UserSignature::Simple(SimpleSignature::Ed25519 {
582                        signature,
583                        public_key,
584                    }) => ReadableUserSignatureRef::Ed25519 {
585                        signature,
586                        public_key,
587                    },
588                    UserSignature::Simple(SimpleSignature::Secp256k1 {
589                        signature,
590                        public_key,
591                    }) => ReadableUserSignatureRef::Secp256k1 {
592                        signature,
593                        public_key,
594                    },
595                    UserSignature::Simple(SimpleSignature::Secp256r1 {
596                        signature,
597                        public_key,
598                    }) => ReadableUserSignatureRef::Secp256r1 {
599                        signature,
600                        public_key,
601                    },
602                    UserSignature::Multisig(multisig) => {
603                        ReadableUserSignatureRef::Multisig(multisig)
604                    }
605                    UserSignature::ZkLogin(zklogin) => ReadableUserSignatureRef::ZkLogin(zklogin),
606                    UserSignature::Passkey(passkey) => ReadableUserSignatureRef::Passkey(passkey),
607                };
608                readable.serialize(serializer)
609            } else {
610                match self {
611                    UserSignature::Simple(simple) => simple.serialize(serializer),
612                    UserSignature::Multisig(multisig) => multisig.serialize(serializer),
613                    UserSignature::ZkLogin(zklogin) => zklogin.serialize(serializer),
614                    UserSignature::Passkey(passkey) => passkey.serialize(serializer),
615                }
616            }
617        }
618    }
619
620    impl<'de> serde::Deserialize<'de> for UserSignature {
621        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
622        where
623            D: serde::Deserializer<'de>,
624        {
625            if deserializer.is_human_readable() {
626                let readable = ReadableUserSignature::deserialize(deserializer)?;
627                Ok(match readable {
628                    ReadableUserSignature::Ed25519 {
629                        signature,
630                        public_key,
631                    } => Self::Simple(SimpleSignature::Ed25519 {
632                        signature,
633                        public_key,
634                    }),
635                    ReadableUserSignature::Secp256k1 {
636                        signature,
637                        public_key,
638                    } => Self::Simple(SimpleSignature::Secp256k1 {
639                        signature,
640                        public_key,
641                    }),
642                    ReadableUserSignature::Secp256r1 {
643                        signature,
644                        public_key,
645                    } => Self::Simple(SimpleSignature::Secp256r1 {
646                        signature,
647                        public_key,
648                    }),
649                    ReadableUserSignature::Multisig(multisig) => Self::Multisig(multisig),
650                    ReadableUserSignature::ZkLogin(zklogin) => Self::ZkLogin(zklogin),
651                    ReadableUserSignature::Passkey(passkey) => Self::Passkey(passkey),
652                })
653            } else {
654                use serde_with::DeserializeAs;
655
656                let bytes: std::borrow::Cow<'de, [u8]> =
657                    serde_with::Bytes::deserialize_as(deserializer)?;
658                Self::from_serialized_bytes(bytes)
659            }
660        }
661    }
662
663    #[cfg(test)]
664    mod test {
665        use super::*;
666        use base64ct::Base64;
667        use base64ct::Encoding;
668        use test_strategy::proptest;
669
670        #[cfg(target_arch = "wasm32")]
671        use wasm_bindgen_test::wasm_bindgen_test as test;
672
673        #[proptest]
674        fn roundtrip_signature_scheme(scheme: SignatureScheme) {
675            assert_eq!(Ok(scheme), SignatureScheme::from_byte(scheme.to_u8()));
676        }
677
678        #[test]
679        fn simple_fixtures() {
680            const FIXTURES: &[(SignatureScheme, &str)]  = &[
681                (SignatureScheme::Ed25519, "YQDaeO4w2ULMy5eqHBzP0oalr1YhDX/9uJS9MntKnW3d55q4aqZYYnoEloaBmXKc6FoD5bTwONdwS9CwdMQGhIcPDX2rNYyNrapO+gBJp1sHQ2VVsQo2ghm7aA9wVxNJ13U="),
682                (SignatureScheme::Secp256k1, "YgErcT6WUSQXGD1DaIwls5rWq648akDMlvL41ugUUhyIPWnqURl+daQLG+ILNemARKHYVNOikKJJ8jqu+HzlRa5rAg4XzVk55GsZZkGWjNdZkQuiV34n+nP944dtub7FvOsr"),
683                (SignatureScheme::Secp256r1, "YgLp1p4K9dSQTt2AeR05yK1MkXmtLm6Sieb9yfkpW1gOBiqnO9ZKZiWUrLJQav2Mxw64zM37g3IVdsB/To6qfl8IA0f7ryPwOKvEwwiicRF6Kkz/rt28X/gcdRe8bHSn7bQw"),
684            ];
685
686            for (scheme, fixture) in FIXTURES {
687                let bcs = Base64::decode_vec(fixture).unwrap();
688
689                let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
690                assert_eq!(*scheme, sig.scheme());
691                let bytes = bcs::to_bytes(&sig).unwrap();
692                assert_eq!(bcs, bytes);
693
694                let json = serde_json::to_string_pretty(&sig).unwrap();
695                println!("{json}");
696                assert_eq!(sig, serde_json::from_str(&json).unwrap());
697            }
698        }
699
700        #[test]
701        fn legacy_multisig_fixtures() {
702            const FIXTURE1: &str = "rgIDAgAnwUSyrALP8m0eEPZE6aPggBELk72n1u3LU+i4nx5kqzhahcICbskEYzHJrbarvFr/RQITgDMoorqpDhN8dgsKATyrN3CD8g37D60dYiGW6sOBqIcf3E1mdMsKvX2pbOZsYQv8VNL+2Jz3vnMXcwEZF32PplKjcnmyUGRhV11M7n4UOjAAAAEAAAAAAAEAEAAAAAAAAQADLEFBMTlxeldNamEycVR2b0FTYWRiQjBObFZiRUtOb0ladTJnUGNGY1RTZGQxATBBUUlPRjgxWk9lUnJHV1pCbG96WFdaRUxvbGQrSi9wei9lT0hiYm0reGJ6ckt3PT0BMEFnTkgrNjhqOERpcnhNTUlvbkVSZWlwTS82N2R2Ri80SEhVWHZHeDBwKzIwTUE9PQECAA==";
703
704            const FIXTURE2: &str = "8QIDAwDYAAra4KQGp2Oq1TCOgWfH8IxC4UA5wJB/NqOcNmMh54Y5d5pnVQfTlqgq4J17a8+W+y3+jk9h4YMB9LzPDYcLAaJJBH+WLPfPaQ7T3Cv8nqpZ1TbPrT8E61FrSgeIbN4OTJeijjguv1pd3ImvTeo4AMYZczf5OH6+5yBaur7R6YACiooT5J36agjUk0TpVcTKMGwykIwD7NBkZ0gbinHxuVJwdi1tSbqhMpqvNgP+CFO6F7FSTe+xiHh0MDOKyYQItxY6MAAAAQAAAAAAAgAQAAAAAAABAAIAAyxBQTE5cXpXTWphMnFUdm9BU2FkYkIwTmxWYkVLTm9JWnUyZ1BjRmNUU2RkMQEwQVFJT0Y4MVpPZVJyR1daQmxvelhXWkVMb2xkK0ovcHovZU9IYmJtK3hienJLdz09ATBBZ05IKzY4ajhEaXJ4TU1Jb25FUmVpcE0vNjdkdkYvNEhIVVh2R3gwcCsyME1BPT0BAgA=";
705
706            for fixture in [FIXTURE1, FIXTURE2] {
707                let bcs = Base64::decode_vec(fixture).unwrap();
708
709                let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
710                assert_eq!(SignatureScheme::Multisig, sig.scheme());
711                let bytes = bcs::to_bytes(&sig).unwrap();
712                assert_eq!(bcs, bytes);
713
714                let json = serde_json::to_string_pretty(&sig).unwrap();
715                println!("{json}");
716                assert_eq!(sig, serde_json::from_str(&json).unwrap());
717            }
718        }
719
720        #[test]
721        fn multisig_fixtures() {
722            const FIXTURE1: &str = "sgIDAwCTLgVngjC4yeuvpAGKVkgcvIKVFUJnL1r6oFZScQVE5DNIz6kfxAGDRcVUczE9CUb7/sN/EuFJ8ot86Sdb8pAFASoQ91stRHXdW5dLy0BQ6v+7XWptawy2ItMyPk508p+PHdtZcm2aKl3lZGIvXe6MPY73E+1Hakv/xJbTYsw5SPMC5dx3gBwxds2GV12c7VUSqkyXamliSF1W/QBMufqrlmdIOZ1ox9gbsvIPtXYahfvKm8ozA7rsZWwRv8atsnyfYgcAAwANfas1jI2tqk76AEmnWwdDZVWxCjaCGbtoD3BXE0nXdQEBAg4XzVk55GsZZkGWjNdZkQuiV34n+nP944dtub7FvOsrAQIDR/uvI/A4q8TDCKJxEXoqTP+u3bxf+Bx1F7xsdKfttDABAgA=";
723
724            const FIXTURE2: &str = "8QEDAgBMW4Oq7XMjO5c6HLgTBJrWDZsCEcZF2EPOf68fdf1aY3e3pvA3cmk0tjMmXFB9+A6J2NohCpTFb/CsXEBjtCcMAfraaMMOMzG815145jlrY44Rbp0d1JQJOJ3hjgEe2xVBFP3QR94IVZk6ssyYxsecpBA+re5eqVRacvZGSobNPkMDAAMADX2rNYyNrapO+gBJp1sHQ2VVsQo2ghm7aA9wVxNJ13UBAQIOF81ZOeRrGWZBlozXWZELold+J/pz/eOHbbm+xbzrKwECA0f7ryPwOKvEwwiicRF6Kkz/rt28X/gcdRe8bHSn7bQwAQIA";
725
726            for fixture in [FIXTURE1, FIXTURE2] {
727                let bcs = Base64::decode_vec(fixture).unwrap();
728
729                let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
730                assert_eq!(SignatureScheme::Multisig, sig.scheme());
731                let bytes = bcs::to_bytes(&sig).unwrap();
732                assert_eq!(bcs, bytes);
733
734                let json = serde_json::to_string_pretty(&sig).unwrap();
735                println!("{json}");
736                assert_eq!(sig, serde_json::from_str(&json).unwrap());
737            }
738        }
739
740        #[test]
741        fn mutisig_with_zklogin() {
742            const FIXTURE: &str = "xwgDAQOWBwUDTDYyNzM5OTI5NDQyODI2NTYyNDE2NDMyNDk5Njc1NDY0MzY0MTU2ODM1MzgzMzAwNzMzMDkwMzgyOTUwOTAwMjA0MzcwMzI3MzQ0MTdNMTM5MjUxMzE5MTUzODM4NDMwOTkzODU1NTU2MjYyNzIwMzI5NjE5MjM3MjY1ODAyMjY2OTcwMTUzMTkxOTcxMzIxODkxMTg2MDUyNTcBMQMCTDc3MDQwMDc2MTQxMjAyNDQ0MjgyMDMyMzQwMzI3NzQ2ODkwODEwNzg2Mzg4NjkzMTcyNDM1NTEyNTMwMTA3MjYzMzg1MTA0MzYxMjdMNDczMzY5MTU2NjAwODE5MTIwNDAxMjcwNTc5OTA2MjI3NTk2MjY0NzMwMTUyNDU3MDIxMjM0MzczMjc1MTE3MTQyMjY2MzEzNTc1MgJMOTYzMjExNjUzNzQxMTQ3Mjk4MTQ2NDE0NzY0MDM5MzkxNzQxODQyMDI4NzgwOTUxODYyMTk5OTM0MjIwNjc2ODgzMjg0NzY5NTg5Nkw4NDM2Mjg3MTUwMzIxMjE2NTUwOTIxNTQ4ODg0MjI2MDM4MjczMTk0MjAyNDQwNTc0NzI5MDM4MTk2NDAxNDAzMDI0Mzg0MTEzODk4AgExATADTDUxNzIxODQyMDU0ODkxNDg4MzEwNTgxODkxNDIwNjI3Njc1NTM3MjMxMDkzNzIyMDk4NzI0NDAxMzA1MTg0MzYzODQxNzUxMjY1MjRMNTE1MTQzMjA2NjEzODc0NzIwOTEyMDY4NzUyMjIwODU1NDA0MTU2NDgyNzA4MDc5NzA1MDcxNjkyNzc2OTY0MzQ0NzQyMjEyMzI3MAExMXdpYVhOeklqb2lhSFIwY0hNNkx5OXBaQzUwZDJsMFkyZ3VkSFl2YjJGMWRHZ3lJaXcCMmV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNJc0ltdHBaQ0k2SWpFaWZRTTIwNjg3NjQyNTE3NjMwNzMzMjczNjg3Nzk1NDc2MjQ3NDM3NzQzODM0NjAxMTAxNTY2Njg0OTY3OTY3NzA1ODA5OTg1MjQxMDY1NTM5CgAAAAAAAABhANFnRWP0VWDZA6kp8ltYtndCLMp70+CQMkW4CKPMOF5fGqTuUIKzqHJysBK8jS3rgHHBc5ZDqn0YUG0W2SH5gQC5xu4WMO8+cRFEpkjbBruyKE9ydM++5T/87lA8waSSAAgABAANfas1jI2tqk76AEmnWwdDZVWxCjaCGbtoD3BXE0nXdQEBAg4XzVk55GsZZkGWjNdZkQuiV34n+nP944dtub7FvOsrAQIDR/uvI/A4q8TDCKJxEXoqTP+u3bxf+Bx1F7xsdKfttDABAzwbaHR0cHM6Ly9pZC50d2l0Y2gudHYvb2F1dGgyLbzKbLI5Mq4c7y9X5gf73CthASNbTN9llO2Okr5TqEMBAQA=";
743
744            let bcs = Base64::decode_vec(FIXTURE).unwrap();
745
746            let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
747            assert_eq!(SignatureScheme::Multisig, sig.scheme());
748            let bytes = bcs::to_bytes(&sig).unwrap();
749            assert_eq!(bcs, bytes);
750
751            let json = serde_json::to_string_pretty(&sig).unwrap();
752            println!("{json}");
753            assert_eq!(sig, serde_json::from_str(&json).unwrap());
754        }
755
756        #[test]
757        fn zklogin_fixtures() {
758            const FIXTURES: &[&str]  = &[
759                "mAcFA00yMTM0MzA3MTg2NDQ3ODc4NTU1OTU1OTY2Njg3NDQ3Njg0MzYyODQxNjA4OTQ4ODEyMTk4MjQ0OTY0ODk4OTg3OTkxMTI1MTY2OTA2N0w1MzYyMzAzOTQxMzk3NzQ1MTk2MTQxNjgxNjA5MDk0MDI4MTg3NzgxMzY2ODc3ODA5NTA2NTU0NzA3MjQ4MzcwNzM4OTcwOTI5MzYwATEDAk0xOTAzMjkyNDMyMDAxODEyNjcyNzEyMDYzMjYzMzM2OTE1NTg2MDc4NDA0NjY2MDcyMzIzMjU0MTAwMjQyODAxODA4ODQ4MTI3MzA5N0sxOTM0MDEzODQwOTcyNjc5OTM0MzgxMTI2ODg3OTQ2MTk1NDk5NTczMjY3NTE5ODAxNDA4MzQ2MzA3NDA2NzI3NjIxNzI0MTA4ODUCTDQxMTc0OTU3NjIwNzc2NjE4OTk2Njk5ODU1MTUzMzc2MDcwMTkzNTgwMjc2MjUxNTc4MDQwMTc0NTI2OTM1MTY5ODY1MDU1NDcyMTdNMTI3MDM0MzkzNTYyNTQ3NTM4NDA5NzAxMjA3MDAxMjM5MjcxOTU1OTI4OTE0MDgxMzY5NzQ0ODkwMzkzMzgyOTgzODYwODQxODYyNzYCATEBMANMNjAyNTg2MDg4MjI2OTUxNTE2NDY3MjY1NjU3OTU4MDE1OTMyMTI2ODY4MDM1NjU0NTkxOTA1NDkwNzkzNTM4MzY1NDYwNzA5MTIyOE0xNTUxNzY4ODA2NDc3NTgzMDI3NzAwNjY2NzE2OTM2NzAxNjU4Nzk5NDIyNjc1MTQ0Nzg5ODMzNjg0MDk5NjU4MDczNzg0NDY0NDExNQExMXdpYVhOeklqb2lhSFIwY0hNNkx5OXBaQzUwZDJsMFkyZ3VkSFl2YjJGMWRHZ3lJaXcCMmV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNJc0ltdHBaQ0k2SWpFaWZRTDIwMjIzNjc3MTc2ODYwNzEyNzk5MTIwNjA0MTY1NTc3MDEyMjMyOTk3NTc0MjQwNjg2MDUwMzc1OTc1MTI1NzUzNDA0NDU0MTY4MTAKAAAAAAAAAGICUv1c+GW7/G0rKAO5QgQrqs3ujZALi4GWTkqgEjfTqMs53H1MeeRJdWzJW104/97F1VJyjm01ozKRasbRJGSsRwKi14vTFJZpnOkPlaKtNt4cGpY4PpaoeXb289IzLDx1Gg==",
760                "mwcFA00xMDE2MjI2MTYwOTg0NDYxNDI1OTY3MjA3OTg1MTYyNzUxNTQyNjEzMzM1OTEzMTc5NDQ3ODc4MDgzNDA3NTkxNDc5ODcxNzMzNzUzNU0xNjUwMTEzNTg2OTk2NDUwMDk1Njk2MDE2NzI0NzgwMzY3MzkyNDI4NDI0NTU3MDIyODMyODc4MDYxNjE4NzE0MzY2MzgzNzA0MjMyNAExAwJMNjAyMjIxMDk3ODA0MDA5MTgyMjQ1MDM2NjM2NjkyMzE1Mjg2NDAzMDQzNjY2ODg5NTUzNzYwNTM5MTM4MDA3OTAxMzIzMjE5OTk2NU0xNjEwNjE0MDY4NzEwMDc3MzQyNDIyNTI0NjEyNzM3ODIyNTgwOTIxMTQxMTYwMjQzMTIwMzI3NDM2MjM1NjEwOTI5NDk5Mjg2MjM4NgJMNzQwNDE3NTg3NDgyOTU3NDM0NTk1NDk1MTU0NDkxODY2ODI5ODQ0OTYxNjMzMDAyMzE4MzE4MzcwMTgxNjEwOTg3OTAwOTY5MTcxMUw3MzAwNzMwODk0MDQzNjM0NjI0NzIwNzkzNDIxNTM1NTUxODI3NDU4NjE4NzU5NjE2OTEzMjU0ODY4MzUzODE1MzM5ODg3MjIzMTA5AgExATADTTExNDA2NTA2NzUyNTkyODQ5NDk4MzcyNzYxODIyNzM4MjA2NTY0ODc4ODM3NTE3NzkxNTY2MzQ3NDk0NDkyNDQyMTI4MDExMTQwMzU3TTE1Njk5MzYzODA5ODg4MDc3MDcxNjM1NTg1MTA2NzA2MjE0NTcxMDI3NDU3ODE5MTE4NTE1NTk2MjA4MDgzODUzODcyOTM3NzQxNDczATExd2lhWE56SWpvaWFIUjBjSE02THk5cFpDNTBkMmwwWTJndWRIWXZiMkYxZEdneUlpdwIyZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0lzSW10cFpDSTZJakVpZlFNMTc1NzI2MTY4NDgyNzU4OTMzODIyMTc0ODE3OTM5MTkwMDYzNjYzNzY4NTk4MTcwNDA1NDYwNDk4MzU5NTgxODc0NjEyOTg2NjkyNzAKAAAAAAAAAGICl9lwjktCQkH7GqGGV6EdbjHv4Go6MIDmr6EIvtg/2h5IuXKJF5GoVLuykxWwkSdNr9iRUZaz3Z0p/Z9nPJlW/gNaiwdVCMdfShJHSZgqfSH4DZpfaJPkGp6VX+TIIeDevg==",
761                "mgcFA00xOTUwNDI1NDE5MzgxMzM3OTA5NDA1MzkyODkyNTQwMjAxMjIxMTg4ODY5MDAzOTQ3ODM0MjYzOTk4OTcwMjA4MjAxNjY2MDkyNzg4MU0xODEwMjYxODU0NjY0NjY3MDgyMjI5MjczMjIwMDgzMzU0OTk4NDAxMTkxMDI1MDY2MjQ4Mjk5MjMzODgzNjA1NTc1MzMyNTUyMTUzMwExAwJMNTI0MzA1OTQ2MTI1NDQxOTM0NzgzOTMxMjI4ODQ5NjY4OTI0Njk4NzIyMTMyMDcxMDcyNzc2NzgzNzc3NDc4ODI4Mzc1NjgzMTAyOE0xMjA3MDIwMzk2MzAzNjY0NTY2NjAyMzUwNDMyNDM3NDY1OTYwMTY1NzY2NDAzOTU4MzE0MDU2Njc2MDExOTcwMTA3MjI5MjA0NzkxMQJNMTYzNjc2NDUxMTMxNzA1OTkxMTgwNzc1NjgxOTUyMjA5ODY1NjcxNjE0ODk2MDcyNDI1NzQ2ODg5ODQ0NzI4NTk0MzE2Mzk4MzQxNzhMNTg5MTQ4MzY3MjI1MTQyMzgzODE5NTQxNDg0NjEwNTY0Nzk4MDE2NjAyODIyNjcwMzE2ODE1Njg2MzkzNjUxNjk1OTkzMjE4MzExNQIBMQEwA0w2NDc2MTA0MzAwODgxNTQ2NTk3NjUwODk0NjEzNTUyMDc1NDg4Mjk5NjA4NjM5MTY4MzE3MjgzNTg2ODI3MDA3MTUzODg5MjI1MTI2TDQ3NjgzNjQxMTE1NjM0NzI0MDI1NzA4NDE0ODEyMDMzMTgzMDQzMTQ1MDQ4NjcxMzk1NzQ0MzAzODI2NzA4MDcwMTkwNDgxMTQyNzEBMTF3aWFYTnpJam9pYUhSMGNITTZMeTlwWkM1MGQybDBZMmd1ZEhZdmIyRjFkR2d5SWl3AjJleUpoYkdjaU9pSlNVekkxTmlJc0luUjVjQ0k2SWtwWFZDSXNJbXRwWkNJNklqRWlmUU0xMDc0MzE4MDg0MjY5ODE2Mzk0ODQ5NzAyMjkwMDE0Mzc4NjI0MTEwOTYyMzMyMDgzNzYxNzUzMDY5NzUxNDA1MzIwODA1NjEwNzgzNAoAAAAAAAAAYgLL7Jn3QV4USqVbuv97w4LqA12BAwU95fsUrvymgAUPtiepsG6kCVnX903PFZBusNM07tgWJ4/5ypb5mbJQhijJA+3BG7HM6kM2jZ0NPldx4AR5zvu+l4ZXRC4lo39h/K5s",
762                "mgcFA0wxNjY4NTEwOTQ1NDY2OTQ2OTYyODUxODAzOTg1MTA3Mjk2NTM1OTM3MzI1NzI5OTMzNDE1MzAzOTcwNjI2MjE3NzAwOTM0NjE4MjY1TDc5ODAxMjUwNTYxMTA2NzczMjY0NjA1MjI0MjgyNTk1OTM4NzQzOTg5MjE3Nzg1Mzk1MTUxODY3MTkwMzk3OTc1MTQ0NDA4ODQ1NTEBMQMCTTEyODA2ODY2NjkyMTUxODMxMTI1MzExMTk3Nzc1NTAxNDU1MTIwNzQwNjg2Mzk2OTQ4NDIxMjAyODI0MjkwODMwNzQzMzM4NTE1MjMxTTE4NzY2Mzc4MTcwNzE4MDMzMzk0ODQxMTYxMTU0MjA0NDA2ODc0MDM0ODk4NjA1NTk4MTgzMDM5NjM2NjQ1NjU3Mjk3NTIzMTU4ODU1Ak0xNzYyNTIzNTA0NzgxNDg2NDg1OTY1NTA1MTkyNTUyMzYxNjkwNzg2MDk3MjM3ODE1OTU1NjA4NDMyNDM5NTQxODk5MzI4NzQwMzk0M00xNjQ3MTA2MDIyOTUzMDIyNjEwOTk0Mzc3MTU3NzQ1NjIzMDM2NTM5NTMxNzM0NDk3OTAwNjAwMTE1NTgxNzM5ODE1NjczMjIwMjcxMwIBMQEwA00xODU1NzU4NTE1MjgxMTk5Mzk1MTY2NDY4NDA1ODg4MTg0NDE2MjY4NTk1NzAxMDY1MzIyNjg5ODkyOTgwNjA1Njc4NjMyMzg5MzA0M0wyNDQ2NDI2NDg4NTQwNzcwNzE5NTIyMjk1NTY3Njc2OTU3MzYzNjIxNTQ0MDUwMTg5OTAxMTk0MTY3NDY1NDE3OTA0Njk2NDQ3NDA1ATExd2lhWE56SWpvaWFIUjBjSE02THk5cFpDNTBkMmwwWTJndWRIWXZiMkYxZEdneUlpdwIyZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0lzSW10cFpDSTZJakVpZlFMODQ2ODk2NzMyOTAyOTgzNjU0MjM3MzIzMjc4Njc3NzgyNDA5MTgyOTM1OTA4MjczNzA5MjQ3MjM1NDEwODEzNTkwOTE0MTM4MjEwNAoAAAAAAAAAYgEaWZZP7C934LS3vgsXYQk85BBiG6E285TY0C6U59qaUxlCUQWACVbxyEej193U4uIIP71lZ6KwvfT7lqOsUUIvAoa8xwWZ68Qgs7iXfsxg5ZS7VnSb6qVi1/gKm9//yqod",
763                "lgcFA0w2MjczOTkyOTQ0MjgyNjU2MjQxNjQzMjQ5OTY3NTQ2NDM2NDE1NjgzNTM4MzMwMDczMzA5MDM4Mjk1MDkwMDIwNDM3MDMyNzM0NDE3TTEzOTI1MTMxOTE1MzgzODQzMDk5Mzg1NTU1NjI2MjcyMDMyOTYxOTIzNzI2NTgwMjI2Njk3MDE1MzE5MTk3MTMyMTg5MTE4NjA1MjU3ATEDAkw3NzA0MDA3NjE0MTIwMjQ0NDI4MjAzMjM0MDMyNzc0Njg5MDgxMDc4NjM4ODY5MzE3MjQzNTUxMjUzMDEwNzI2MzM4NTEwNDM2MTI3TDQ3MzM2OTE1NjYwMDgxOTEyMDQwMTI3MDU3OTkwNjIyNzU5NjI2NDczMDE1MjQ1NzAyMTIzNDM3MzI3NTExNzE0MjI2NjMxMzU3NTICTDk2MzIxMTY1Mzc0MTE0NzI5ODE0NjQxNDc2NDAzOTM5MTc0MTg0MjAyODc4MDk1MTg2MjE5OTkzNDIyMDY3Njg4MzI4NDc2OTU4OTZMODQzNjI4NzE1MDMyMTIxNjU1MDkyMTU0ODg4NDIyNjAzODI3MzE5NDIwMjQ0MDU3NDcyOTAzODE5NjQwMTQwMzAyNDM4NDExMzg5OAIBMQEwA0w1MTcyMTg0MjA1NDg5MTQ4ODMxMDU4MTg5MTQyMDYyNzY3NTUzNzIzMTA5MzcyMjA5ODcyNDQwMTMwNTE4NDM2Mzg0MTc1MTI2NTI0TDUxNTE0MzIwNjYxMzg3NDcyMDkxMjA2ODc1MjIyMDg1NTQwNDE1NjQ4MjcwODA3OTcwNTA3MTY5Mjc3Njk2NDM0NDc0MjIxMjMyNzABMTF3aWFYTnpJam9pYUhSMGNITTZMeTlwWkM1MGQybDBZMmd1ZEhZdmIyRjFkR2d5SWl3AjJleUpoYkdjaU9pSlNVekkxTmlJc0luUjVjQ0k2SWtwWFZDSXNJbXRwWkNJNklqRWlmUU0yMDY4NzY0MjUxNzYzMDczMzI3MzY4Nzc5NTQ3NjI0NzQzNzc0MzgzNDYwMTEwMTU2NjY4NDk2Nzk2NzcwNTgwOTk4NTI0MTA2NTUzOQoAAAAAAAAAYQBn1v6x7RD9EyaiubLQ8qQkJSNI2Mr1GFHXZyOUJ+eCphFkwjYKBo44TMAbryd405BY+MHYTFLZOD06UTycKHgKucbuFjDvPnERRKZI2wa7sihPcnTPvuU//O5QPMGkkgA=",
764            ];
765
766            for fixture in FIXTURES {
767                let bcs = Base64::decode_vec(fixture).unwrap();
768
769                let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
770                assert_eq!(SignatureScheme::ZkLogin, sig.scheme());
771                let bytes = bcs::to_bytes(&sig).unwrap();
772                assert_eq!(bcs, bytes);
773
774                let json = serde_json::to_string_pretty(&sig).unwrap();
775                println!("{json}");
776                assert_eq!(sig, serde_json::from_str(&json).unwrap());
777            }
778        }
779
780        #[test]
781        fn passkey_fixtures() {
782            const FIXTURES: &[&str]  = &[
783                "lgIGJUmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjHQAAAACKAXsidHlwZSI6IndlYmF1dGhuLmdldCIsImNoYWxsZW5nZSI6IkFBQUF0X21qSUIxdmJWcFlNNldWNllfb2l4Nko4YU5fOXNiOFNLRmJ1a0JmaVF3Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDo1MTczIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfWICmOyQv1fJ+inKD0C/sxKtxyFKl9aoBign6p9Ih3iA2ahDVg2CPZqUOlEhur2S2GbIZjbn6TbgWtbXXg8SjLkL7wM9Fw4JO0AKLdnLC1nhQguHBX5K6Hv2ta1sqoOqEFDDEw==",
784            ];
785
786            for fixture in FIXTURES {
787                let bcs = Base64::decode_vec(fixture).unwrap();
788
789                let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
790                assert_eq!(SignatureScheme::Passkey, sig.scheme());
791                let bytes = bcs::to_bytes(&sig).unwrap();
792                assert_eq!(bcs, bytes);
793
794                let json = serde_json::to_string_pretty(&sig).unwrap();
795                println!("{json}");
796                assert_eq!(sig, serde_json::from_str(&json).unwrap());
797            }
798        }
799
800        #[test]
801        fn mutisig_with_passkey() {
802            const FIXTURE: &str = "4wMDAQSPAgYlWA5npzp6kvrYZs+ZuUq2Z1mil2S1cYIfq64uix17NuQdAAAAAIMBeyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoieEtoSGhUU1o4TVJTNjAtLTZNbjBreC1vSW1RWUs1RjNFMmtzQm9iRkk3OCIsIm9yaWdpbiI6Imh0dHBzOi8vd3d3LnN1aS5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX1iAj6cOZNgD7buVIny/mQVv0gt87gEpo/V6yFusFHc0ED0XBdBXIRO8cDcoKDOPeKpNOwyMn4JvCwh/bA9Z27vBcID4FVY2uPg1vTXoKTq74rVS0uaUzafqn5emXJEfpzp9osQAAUADX2rNYyNrapO+gBJp1sHQ2VVsQo2ghm7aA9wVxNJ13UBAQIOF81ZOeRrGWZBlozXWZELold+J/pz/eOHbbm+xbzrKwECA0f7ryPwOKvEwwiicRF6Kkz/rt28X/gcdRe8bHSn7bQwAQM8G2h0dHBzOi8vaWQudHdpdGNoLnR2L29hdXRoMgVuAvSJovCe0hhp6n7cBfcDd20d7RhhkODYMqLqqMIDAQQD4FVY2uPg1vTXoKTq74rVS0uaUzafqn5emXJEfpzp9osBAQA=";
803
804            let bcs = Base64::decode_vec(FIXTURE).unwrap();
805
806            let sig: UserSignature = bcs::from_bytes(&bcs).unwrap();
807            assert_eq!(SignatureScheme::Multisig, sig.scheme());
808
809            let committee = match &sig {
810                UserSignature::Multisig(multisig) => multisig.committee(),
811                _ => panic!("not a multisig"),
812            };
813            assert_eq!(
814                committee.derive_address(),
815                crate::Address::from_hex(
816                    "0x10f58251fa90d7fd5510f99787ac5c5874fe29c033524ba0275f1ed793ed8598"
817                )
818                .unwrap()
819            );
820
821            let bytes = bcs::to_bytes(&sig).unwrap();
822            assert_eq!(bcs, bytes);
823
824            let json = serde_json::to_string_pretty(&sig).unwrap();
825            println!("{json}");
826            assert_eq!(sig, serde_json::from_str(&json).unwrap());
827        }
828    }
829}