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