Skip to main content

sui_rpc/proto/sui/rpc/v2/
signatures.rs

1use super::*;
2use crate::field::FieldMaskTree;
3use crate::merge::Merge;
4use crate::proto::TryFromProtoError;
5use tap::Pipe;
6
7//
8// ValidatorAggregatedSignature
9//
10
11impl From<sui_sdk_types::ValidatorAggregatedSignature> for ValidatorAggregatedSignature {
12    fn from(value: sui_sdk_types::ValidatorAggregatedSignature) -> Self {
13        let mut bitmap = Vec::new();
14        value.bitmap.serialize_into(&mut bitmap).unwrap();
15
16        Self {
17            epoch: Some(value.epoch),
18            signature: Some(value.signature.as_bytes().to_vec().into()),
19            bitmap: Some(bitmap.into()),
20        }
21    }
22}
23
24impl TryFrom<&ValidatorAggregatedSignature> for sui_sdk_types::ValidatorAggregatedSignature {
25    type Error = TryFromProtoError;
26
27    fn try_from(value: &ValidatorAggregatedSignature) -> Result<Self, Self::Error> {
28        let epoch = value
29            .epoch
30            .ok_or_else(|| TryFromProtoError::missing("epoch"))?;
31        let signature = value
32            .signature
33            .as_ref()
34            .ok_or_else(|| TryFromProtoError::missing("signature"))?
35            .as_ref()
36            .pipe(sui_sdk_types::Bls12381Signature::from_bytes)
37            .map_err(|e| {
38                TryFromProtoError::invalid(ValidatorAggregatedSignature::SIGNATURE_FIELD, e)
39            })?;
40        let bitmap = sui_sdk_types::Bitmap::deserialize_from(value.bitmap()).map_err(|e| {
41            TryFromProtoError::invalid(ValidatorAggregatedSignature::BITMAP_FIELD, e)
42        })?;
43
44        Ok(Self {
45            epoch,
46            signature,
47            bitmap,
48        })
49    }
50}
51
52//
53// ValidatorCommitteeMember
54//
55
56impl From<sui_sdk_types::ValidatorCommitteeMember> for ValidatorCommitteeMember {
57    fn from(value: sui_sdk_types::ValidatorCommitteeMember) -> Self {
58        Self {
59            public_key: Some(value.public_key.as_bytes().to_vec().into()),
60            weight: Some(value.stake),
61        }
62    }
63}
64
65impl TryFrom<&ValidatorCommitteeMember> for sui_sdk_types::ValidatorCommitteeMember {
66    type Error = TryFromProtoError;
67
68    fn try_from(
69        ValidatorCommitteeMember { public_key, weight }: &ValidatorCommitteeMember,
70    ) -> Result<Self, Self::Error> {
71        let public_key = public_key
72            .as_ref()
73            .ok_or_else(|| TryFromProtoError::missing("public_key"))?
74            .as_ref()
75            .pipe(sui_sdk_types::Bls12381PublicKey::from_bytes)
76            .map_err(|e| {
77                TryFromProtoError::invalid(ValidatorCommitteeMember::PUBLIC_KEY_FIELD, e)
78            })?;
79        let stake = weight.ok_or_else(|| TryFromProtoError::missing("weight"))?;
80        Ok(Self { public_key, stake })
81    }
82}
83
84//
85// ValidatorCommittee
86//
87
88impl From<sui_sdk_types::ValidatorCommittee> for ValidatorCommittee {
89    fn from(value: sui_sdk_types::ValidatorCommittee) -> Self {
90        Self {
91            epoch: Some(value.epoch),
92            members: value.members.into_iter().map(Into::into).collect(),
93        }
94    }
95}
96
97impl TryFrom<&ValidatorCommittee> for sui_sdk_types::ValidatorCommittee {
98    type Error = TryFromProtoError;
99
100    fn try_from(value: &ValidatorCommittee) -> Result<Self, Self::Error> {
101        let epoch = value
102            .epoch
103            .ok_or_else(|| TryFromProtoError::missing("epoch"))?;
104        Ok(Self {
105            epoch,
106            members: value
107                .members
108                .iter()
109                .map(TryInto::try_into)
110                .collect::<Result<_, _>>()?,
111        })
112    }
113}
114
115//
116// CircomG1
117//
118
119impl From<sui_sdk_types::CircomG1> for CircomG1 {
120    fn from(value: sui_sdk_types::CircomG1) -> Self {
121        let [e0, e1, e2] = value.0;
122
123        Self {
124            e0: Some(e0.to_string()),
125            e1: Some(e1.to_string()),
126            e2: Some(e2.to_string()),
127        }
128    }
129}
130
131impl TryFrom<&CircomG1> for sui_sdk_types::CircomG1 {
132    type Error = TryFromProtoError;
133
134    fn try_from(value: &CircomG1) -> Result<Self, Self::Error> {
135        let e0 = value
136            .e0
137            .as_ref()
138            .ok_or_else(|| TryFromProtoError::missing("e0"))?
139            .parse()
140            .map_err(|e| TryFromProtoError::invalid(CircomG1::E0_FIELD, e))?;
141        let e1 = value
142            .e1
143            .as_ref()
144            .ok_or_else(|| TryFromProtoError::missing("e1"))?
145            .parse()
146            .map_err(|e| TryFromProtoError::invalid(CircomG1::E1_FIELD, e))?;
147        let e2 = value
148            .e2
149            .as_ref()
150            .ok_or_else(|| TryFromProtoError::missing("e2"))?
151            .parse()
152            .map_err(|e| TryFromProtoError::invalid(CircomG1::E2_FIELD, e))?;
153
154        Ok(Self([e0, e1, e2]))
155    }
156}
157
158//
159// CircomG2
160//
161
162impl From<sui_sdk_types::CircomG2> for CircomG2 {
163    fn from(value: sui_sdk_types::CircomG2) -> Self {
164        let [[e00, e01], [e10, e11], [e20, e21]] = value.0;
165
166        Self {
167            e00: Some(e00.to_string()),
168            e01: Some(e01.to_string()),
169            e10: Some(e10.to_string()),
170            e11: Some(e11.to_string()),
171            e20: Some(e20.to_string()),
172            e21: Some(e21.to_string()),
173        }
174    }
175}
176
177impl TryFrom<&CircomG2> for sui_sdk_types::CircomG2 {
178    type Error = TryFromProtoError;
179
180    fn try_from(value: &CircomG2) -> Result<Self, Self::Error> {
181        let e00 = value
182            .e00
183            .as_ref()
184            .ok_or_else(|| TryFromProtoError::missing("e00"))?
185            .parse()
186            .map_err(|e| TryFromProtoError::invalid(CircomG2::E00_FIELD, e))?;
187        let e01 = value
188            .e01
189            .as_ref()
190            .ok_or_else(|| TryFromProtoError::missing("e01"))?
191            .parse()
192            .map_err(|e| TryFromProtoError::invalid(CircomG2::E01_FIELD, e))?;
193
194        let e10 = value
195            .e10
196            .as_ref()
197            .ok_or_else(|| TryFromProtoError::missing("e10"))?
198            .parse()
199            .map_err(|e| TryFromProtoError::invalid(CircomG2::E10_FIELD, e))?;
200        let e11 = value
201            .e11
202            .as_ref()
203            .ok_or_else(|| TryFromProtoError::missing("e11"))?
204            .parse()
205            .map_err(|e| TryFromProtoError::invalid(CircomG2::E11_FIELD, e))?;
206
207        let e20 = value
208            .e20
209            .as_ref()
210            .ok_or_else(|| TryFromProtoError::missing("e20"))?
211            .parse()
212            .map_err(|e| TryFromProtoError::invalid(CircomG2::E20_FIELD, e))?;
213        let e21 = value
214            .e21
215            .as_ref()
216            .ok_or_else(|| TryFromProtoError::missing("e21"))?
217            .parse()
218            .map_err(|e| TryFromProtoError::invalid(CircomG2::E21_FIELD, e))?;
219
220        Ok(Self([[e00, e01], [e10, e11], [e20, e21]]))
221    }
222}
223
224//
225// ZkLoginClaim
226//
227
228impl From<sui_sdk_types::ZkLoginClaim> for ZkLoginClaim {
229    fn from(
230        sui_sdk_types::ZkLoginClaim { value, index_mod_4 }: sui_sdk_types::ZkLoginClaim,
231    ) -> Self {
232        Self {
233            value: Some(value),
234            index_mod_4: Some(index_mod_4.into()),
235        }
236    }
237}
238
239impl TryFrom<&ZkLoginClaim> for sui_sdk_types::ZkLoginClaim {
240    type Error = TryFromProtoError;
241
242    fn try_from(ZkLoginClaim { value, index_mod_4 }: &ZkLoginClaim) -> Result<Self, Self::Error> {
243        let value = value
244            .as_ref()
245            .ok_or_else(|| TryFromProtoError::missing("value"))?
246            .into();
247        let index_mod_4 = index_mod_4
248            .ok_or_else(|| TryFromProtoError::missing("index_mod_4"))?
249            .try_into()
250            .map_err(|e| TryFromProtoError::invalid(ZkLoginClaim::INDEX_MOD_4_FIELD, e))?;
251
252        Ok(Self { value, index_mod_4 })
253    }
254}
255
256//
257// ZkLoginProof
258//
259
260impl From<sui_sdk_types::ZkLoginProof> for ZkLoginProof {
261    fn from(value: sui_sdk_types::ZkLoginProof) -> Self {
262        Self {
263            a: Some(value.a.into()),
264            b: Some(value.b.into()),
265            c: Some(value.c.into()),
266        }
267    }
268}
269
270impl TryFrom<&ZkLoginProof> for sui_sdk_types::ZkLoginProof {
271    type Error = TryFromProtoError;
272
273    fn try_from(value: &ZkLoginProof) -> Result<Self, Self::Error> {
274        let a = value
275            .a
276            .as_ref()
277            .ok_or_else(|| TryFromProtoError::missing("a"))?
278            .try_into()?;
279        let b = value
280            .b
281            .as_ref()
282            .ok_or_else(|| TryFromProtoError::missing("b"))?
283            .try_into()?;
284        let c = value
285            .c
286            .as_ref()
287            .ok_or_else(|| TryFromProtoError::missing("c"))?
288            .try_into()?;
289
290        Ok(Self { a, b, c })
291    }
292}
293
294//
295// ZkLoginInputs
296//
297
298impl From<sui_sdk_types::ZkLoginInputs> for ZkLoginInputs {
299    fn from(value: sui_sdk_types::ZkLoginInputs) -> Self {
300        Self {
301            proof_points: Some(value.proof_points().clone().into()),
302            iss_base64_details: Some(value.iss_base64_details().clone().into()),
303            header_base64: Some(value.header_base64().into()),
304            address_seed: Some(value.address_seed().to_string()),
305        }
306    }
307}
308
309impl TryFrom<&ZkLoginInputs> for sui_sdk_types::ZkLoginInputs {
310    type Error = TryFromProtoError;
311
312    fn try_from(value: &ZkLoginInputs) -> Result<Self, Self::Error> {
313        let proof_points = value
314            .proof_points
315            .as_ref()
316            .ok_or_else(|| TryFromProtoError::missing("proof_points"))?
317            .try_into()?;
318        let iss_base64_details = value
319            .iss_base64_details
320            .as_ref()
321            .ok_or_else(|| TryFromProtoError::missing("iss_base64_details"))?
322            .try_into()?;
323        let header_base64 = value
324            .header_base64
325            .as_ref()
326            .ok_or_else(|| TryFromProtoError::missing("header_base64"))?
327            .into();
328        let address_seed = value
329            .address_seed
330            .as_ref()
331            .ok_or_else(|| TryFromProtoError::missing("address_seed"))?
332            .parse()
333            .map_err(|e| TryFromProtoError::invalid(ZkLoginInputs::ADDRESS_SEED_FIELD, e))?;
334
335        Self::new(
336            proof_points,
337            iss_base64_details,
338            header_base64,
339            address_seed,
340        )
341        .map_err(|e| TryFromProtoError::invalid("inputs", e))
342    }
343}
344
345//
346// ZkLoginAuthenticator
347//
348
349impl From<sui_sdk_types::ZkLoginAuthenticator> for ZkLoginAuthenticator {
350    fn from(value: sui_sdk_types::ZkLoginAuthenticator) -> Self {
351        let public_identifier = Some(value.inputs.public_identifier().into());
352        let jwk_id = Some(value.inputs.jwk_id().into());
353        Self {
354            inputs: Some(value.inputs.into()),
355            max_epoch: Some(value.max_epoch),
356            signature: Some(value.signature.into()),
357            public_identifier,
358            jwk_id,
359        }
360    }
361}
362
363impl TryFrom<&ZkLoginAuthenticator> for sui_sdk_types::ZkLoginAuthenticator {
364    type Error = TryFromProtoError;
365
366    fn try_from(value: &ZkLoginAuthenticator) -> Result<Self, Self::Error> {
367        let inputs = value
368            .inputs
369            .as_ref()
370            .ok_or_else(|| TryFromProtoError::missing("inputs"))?
371            .try_into()?;
372        let max_epoch = value
373            .max_epoch
374            .ok_or_else(|| TryFromProtoError::missing("max_epoch"))?;
375        let signature = value
376            .signature
377            .as_ref()
378            .ok_or_else(|| TryFromProtoError::missing("signature"))?
379            .try_into()?;
380
381        Ok(Self {
382            inputs,
383            max_epoch,
384            signature,
385        })
386    }
387}
388
389//
390// ZkLoginPublicIdentifier
391//
392
393impl From<&sui_sdk_types::ZkLoginPublicIdentifier> for ZkLoginPublicIdentifier {
394    fn from(value: &sui_sdk_types::ZkLoginPublicIdentifier) -> Self {
395        Self {
396            iss: Some(value.iss().to_owned()),
397            address_seed: Some(value.address_seed().to_string()),
398        }
399    }
400}
401
402impl TryFrom<&ZkLoginPublicIdentifier> for sui_sdk_types::ZkLoginPublicIdentifier {
403    type Error = TryFromProtoError;
404
405    fn try_from(value: &ZkLoginPublicIdentifier) -> Result<Self, Self::Error> {
406        let iss = value
407            .iss
408            .as_ref()
409            .ok_or_else(|| TryFromProtoError::missing("iss"))?
410            .into();
411        let address_seed = value
412            .address_seed
413            .as_ref()
414            .ok_or_else(|| TryFromProtoError::missing("address_seed"))?
415            .parse()
416            .map_err(|e| {
417                TryFromProtoError::invalid(ZkLoginPublicIdentifier::ADDRESS_SEED_FIELD, e)
418            })?;
419
420        Self::new(iss, address_seed)
421            .ok_or_else(|| {
422                TryFromProtoError::invalid(ZkLoginPublicIdentifier::ISS_FIELD, "invalid iss")
423            })?
424            .pipe(Ok)
425    }
426}
427
428//
429// SignatureScheme
430//
431
432impl TryFrom<&SignatureScheme> for sui_sdk_types::SignatureScheme {
433    type Error = TryFromProtoError;
434
435    fn try_from(value: &SignatureScheme) -> Result<Self, Self::Error> {
436        use SignatureScheme::*;
437
438        match value {
439            Ed25519 => Self::Ed25519,
440            Secp256k1 => Self::Secp256k1,
441            Secp256r1 => Self::Secp256r1,
442            Multisig => Self::Multisig,
443            Bls12381 => Self::Bls12381,
444            Zklogin => Self::ZkLogin,
445            Passkey => Self::Passkey,
446            Mldsa65 => Self::MlDsa65,
447        }
448        .pipe(Ok)
449    }
450}
451
452//
453// SimpleSignature
454//
455
456impl From<sui_sdk_types::SimpleSignature> for SimpleSignature {
457    fn from(value: sui_sdk_types::SimpleSignature) -> Self {
458        let (signature, public_key) = match &value {
459            sui_sdk_types::SimpleSignature::Ed25519 {
460                signature,
461                public_key,
462            } => (signature.as_bytes(), public_key.as_bytes()),
463            sui_sdk_types::SimpleSignature::Secp256k1 {
464                signature,
465                public_key,
466            } => (signature.as_bytes(), public_key.as_bytes()),
467            sui_sdk_types::SimpleSignature::Secp256r1 {
468                signature,
469                public_key,
470            } => (signature.as_bytes(), public_key.as_bytes()),
471            sui_sdk_types::SimpleSignature::MlDsa65 {
472                signature,
473                public_key,
474            } => (signature.as_bytes(), public_key.as_bytes()),
475            _ => return Self::default(),
476        };
477
478        Self {
479            scheme: Some(value.scheme().to_u8().into()),
480            signature: Some(signature.to_vec().into()),
481            public_key: Some(public_key.to_vec().into()),
482        }
483    }
484}
485
486impl TryFrom<&SimpleSignature> for sui_sdk_types::SimpleSignature {
487    type Error = TryFromProtoError;
488
489    fn try_from(value: &SimpleSignature) -> Result<Self, Self::Error> {
490        use SignatureScheme;
491        use sui_sdk_types::Ed25519PublicKey;
492        use sui_sdk_types::Ed25519Signature;
493        use sui_sdk_types::Secp256k1PublicKey;
494        use sui_sdk_types::Secp256k1Signature;
495        use sui_sdk_types::Secp256r1PublicKey;
496        use sui_sdk_types::Secp256r1Signature;
497
498        let scheme = value
499            .scheme
500            .ok_or_else(|| TryFromProtoError::missing("scheme"))?
501            .pipe(SignatureScheme::try_from)
502            .map_err(|e| TryFromProtoError::invalid(SimpleSignature::SCHEME_FIELD, e))?;
503        let signature = value
504            .signature
505            .as_ref()
506            .ok_or_else(|| TryFromProtoError::missing("signature"))?;
507        let public_key = value
508            .public_key
509            .as_ref()
510            .ok_or_else(|| TryFromProtoError::missing("public_key"))?;
511
512        match scheme {
513            SignatureScheme::Ed25519 => Self::Ed25519 {
514                signature: Ed25519Signature::from_bytes(signature)
515                    .map_err(|e| TryFromProtoError::invalid(SimpleSignature::SIGNATURE_FIELD, e))?,
516                public_key: Ed25519PublicKey::from_bytes(public_key).map_err(|e| {
517                    TryFromProtoError::invalid(SimpleSignature::PUBLIC_KEY_FIELD, e)
518                })?,
519            },
520            SignatureScheme::Secp256k1 => Self::Secp256k1 {
521                signature: Secp256k1Signature::from_bytes(signature)
522                    .map_err(|e| TryFromProtoError::invalid(SimpleSignature::SIGNATURE_FIELD, e))?,
523                public_key: Secp256k1PublicKey::from_bytes(public_key).map_err(|e| {
524                    TryFromProtoError::invalid(SimpleSignature::PUBLIC_KEY_FIELD, e)
525                })?,
526            },
527            SignatureScheme::Secp256r1 => Self::Secp256r1 {
528                signature: Secp256r1Signature::from_bytes(signature)
529                    .map_err(|e| TryFromProtoError::invalid(SimpleSignature::SIGNATURE_FIELD, e))?,
530                public_key: Secp256r1PublicKey::from_bytes(public_key).map_err(|e| {
531                    TryFromProtoError::invalid(SimpleSignature::PUBLIC_KEY_FIELD, e)
532                })?,
533            },
534            SignatureScheme::Mldsa65 => Self::MlDsa65 {
535                signature: Box::new(
536                    sui_sdk_types::MlDsa65Signature::from_bytes(signature).map_err(|e| {
537                        TryFromProtoError::invalid(SimpleSignature::SIGNATURE_FIELD, e)
538                    })?,
539                ),
540                public_key: Box::new(
541                    sui_sdk_types::MlDsa65PublicKey::from_bytes(public_key).map_err(|e| {
542                        TryFromProtoError::invalid(SimpleSignature::PUBLIC_KEY_FIELD, e)
543                    })?,
544                ),
545            },
546            SignatureScheme::Multisig
547            | SignatureScheme::Bls12381
548            | SignatureScheme::Zklogin
549            | SignatureScheme::Passkey => {
550                return Err(TryFromProtoError::invalid(
551                    SimpleSignature::SCHEME_FIELD,
552                    "invalid or unknown signature scheme",
553                ));
554            }
555        }
556        .pipe(Ok)
557    }
558}
559
560//
561// PasskeyAuthenticator
562//
563
564impl From<sui_sdk_types::PasskeyAuthenticator> for PasskeyAuthenticator {
565    fn from(value: sui_sdk_types::PasskeyAuthenticator) -> Self {
566        Self {
567            authenticator_data: Some(value.authenticator_data().to_vec().into()),
568            client_data_json: Some(value.client_data_json().to_owned()),
569            signature: Some(value.signature().into()),
570        }
571    }
572}
573
574impl TryFrom<&PasskeyAuthenticator> for sui_sdk_types::PasskeyAuthenticator {
575    type Error = TryFromProtoError;
576
577    fn try_from(value: &PasskeyAuthenticator) -> Result<Self, Self::Error> {
578        let authenticator_data = value
579            .authenticator_data
580            .as_ref()
581            .ok_or_else(|| TryFromProtoError::missing("authenticator_data"))?
582            .to_vec();
583        let client_data_json = value
584            .client_data_json
585            .as_ref()
586            .ok_or_else(|| TryFromProtoError::missing("client_data_json"))?
587            .into();
588
589        let signature = value
590            .signature
591            .as_ref()
592            .ok_or_else(|| TryFromProtoError::missing("signature"))?
593            .try_into()?;
594
595        Self::new(authenticator_data, client_data_json, signature).ok_or_else(|| {
596            TryFromProtoError::invalid(
597                PasskeyAuthenticator::CLIENT_DATA_JSON_FIELD,
598                "invalid passkey",
599            )
600        })
601    }
602}
603
604//
605// MultisigMemberPublicKey
606//
607
608impl From<&sui_sdk_types::MultisigMemberPublicKey> for MultisigMemberPublicKey {
609    fn from(value: &sui_sdk_types::MultisigMemberPublicKey) -> Self {
610        use sui_sdk_types::MultisigMemberPublicKey::*;
611
612        let mut message = Self::default();
613
614        let scheme = match value {
615            Ed25519(public_key) => {
616                message.public_key = Some(public_key.as_bytes().to_vec().into());
617                SignatureScheme::Ed25519
618            }
619            Secp256k1(public_key) => {
620                message.public_key = Some(public_key.as_bytes().to_vec().into());
621                SignatureScheme::Secp256k1
622            }
623            Secp256r1(public_key) => {
624                message.public_key = Some(public_key.as_bytes().to_vec().into());
625                SignatureScheme::Secp256r1
626            }
627            ZkLogin(zklogin_id) => {
628                message.zklogin = Some(zklogin_id.into());
629                SignatureScheme::Zklogin
630            }
631            Passkey(public_key) => {
632                message.public_key = Some(public_key.inner().as_bytes().to_vec().into());
633                SignatureScheme::Passkey
634            }
635            MlDsa65(public_key) => {
636                message.public_key = Some(public_key.as_bytes().to_vec().into());
637                SignatureScheme::Mldsa65
638            }
639            _ => return Self::default(),
640        };
641
642        message.set_scheme(scheme);
643        message
644    }
645}
646
647impl TryFrom<&MultisigMemberPublicKey> for sui_sdk_types::MultisigMemberPublicKey {
648    type Error = TryFromProtoError;
649
650    fn try_from(value: &MultisigMemberPublicKey) -> Result<Self, Self::Error> {
651        use sui_sdk_types::Ed25519PublicKey;
652        use sui_sdk_types::Secp256k1PublicKey;
653        use sui_sdk_types::Secp256r1PublicKey;
654
655        match value.scheme() {
656            SignatureScheme::Ed25519 => Self::Ed25519(
657                Ed25519PublicKey::from_bytes(value.public_key()).map_err(|e| {
658                    TryFromProtoError::invalid(MultisigMemberPublicKey::PUBLIC_KEY_FIELD, e)
659                })?,
660            ),
661            SignatureScheme::Secp256k1 => {
662                Self::Secp256k1(Secp256k1PublicKey::from_bytes(value.public_key()).map_err(
663                    |e| TryFromProtoError::invalid(MultisigMemberPublicKey::PUBLIC_KEY_FIELD, e),
664                )?)
665            }
666            SignatureScheme::Secp256r1 => {
667                Self::Secp256r1(Secp256r1PublicKey::from_bytes(value.public_key()).map_err(
668                    |e| TryFromProtoError::invalid(MultisigMemberPublicKey::PUBLIC_KEY_FIELD, e),
669                )?)
670            }
671            SignatureScheme::Zklogin => Self::ZkLogin(
672                value
673                    .zklogin
674                    .as_ref()
675                    .ok_or_else(|| TryFromProtoError::missing("zklogin"))?
676                    .try_into()?,
677            ),
678            SignatureScheme::Passkey => Self::Passkey(sui_sdk_types::PasskeyPublicKey::new(
679                Secp256r1PublicKey::from_bytes(value.public_key()).map_err(|e| {
680                    TryFromProtoError::invalid(MultisigMemberPublicKey::PUBLIC_KEY_FIELD, e)
681                })?,
682            )),
683            SignatureScheme::Mldsa65 => Self::MlDsa65(Box::new(
684                sui_sdk_types::MlDsa65PublicKey::from_bytes(value.public_key()).map_err(|e| {
685                    TryFromProtoError::invalid(MultisigMemberPublicKey::PUBLIC_KEY_FIELD, e)
686                })?,
687            )),
688            SignatureScheme::Multisig | SignatureScheme::Bls12381 => {
689                return Err(TryFromProtoError::invalid(
690                    MultisigMemberPublicKey::SCHEME_FIELD,
691                    "invalid MultisigMemberPublicKey scheme",
692                ));
693            }
694        }
695        .pipe(Ok)
696    }
697}
698
699//
700// MultisigMember
701//
702
703impl From<&sui_sdk_types::MultisigMember> for MultisigMember {
704    fn from(value: &sui_sdk_types::MultisigMember) -> Self {
705        Self {
706            public_key: Some(value.public_key().into()),
707            weight: Some(value.weight().into()),
708        }
709    }
710}
711
712impl TryFrom<&MultisigMember> for sui_sdk_types::MultisigMember {
713    type Error = TryFromProtoError;
714
715    fn try_from(value: &MultisigMember) -> Result<Self, Self::Error> {
716        let public_key = value
717            .public_key
718            .as_ref()
719            .ok_or_else(|| TryFromProtoError::missing("public_key"))?
720            .try_into()?;
721        let weight = value
722            .weight
723            .ok_or_else(|| TryFromProtoError::missing("weight"))?
724            .try_into()
725            .map_err(|e| TryFromProtoError::invalid(MultisigMember::WEIGHT_FIELD, e))?;
726
727        Ok(Self::new(public_key, weight))
728    }
729}
730
731//
732// MultisigCommittee
733//
734
735impl From<&sui_sdk_types::MultisigCommittee> for MultisigCommittee {
736    fn from(value: &sui_sdk_types::MultisigCommittee) -> Self {
737        Self {
738            members: value.members().iter().map(Into::into).collect(),
739            threshold: Some(value.threshold().into()),
740        }
741    }
742}
743
744impl TryFrom<&MultisigCommittee> for sui_sdk_types::MultisigCommittee {
745    type Error = TryFromProtoError;
746
747    fn try_from(value: &MultisigCommittee) -> Result<Self, Self::Error> {
748        let members = value
749            .members
750            .iter()
751            .map(TryInto::try_into)
752            .collect::<Result<_, _>>()?;
753        let threshold = value
754            .threshold
755            .ok_or_else(|| TryFromProtoError::missing("threshold"))?
756            .try_into()
757            .map_err(|e| TryFromProtoError::invalid(MultisigCommittee::THRESHOLD_FIELD, e))?;
758
759        Ok(Self::new(members, threshold))
760    }
761}
762
763//
764// MultisigMemberSignature
765//
766
767impl From<&sui_sdk_types::MultisigMemberSignature> for MultisigMemberSignature {
768    fn from(value: &sui_sdk_types::MultisigMemberSignature) -> Self {
769        use sui_sdk_types::MultisigMemberSignature::*;
770
771        let mut message = Self::default();
772
773        let scheme = match value {
774            Ed25519(signature) => {
775                message.signature = Some(signature.as_bytes().to_vec().into());
776                SignatureScheme::Ed25519
777            }
778            Secp256k1(signature) => {
779                message.signature = Some(signature.as_bytes().to_vec().into());
780                SignatureScheme::Secp256k1
781            }
782            Secp256r1(signature) => {
783                message.signature = Some(signature.as_bytes().to_vec().into());
784                SignatureScheme::Secp256r1
785            }
786            ZkLogin(zklogin_id) => {
787                message.zklogin = Some((**zklogin_id).clone().into());
788                SignatureScheme::Zklogin
789            }
790            Passkey(p) => {
791                message.passkey = Some(p.clone().into());
792                SignatureScheme::Passkey
793            }
794            MlDsa65(signature) => {
795                message.signature = Some(signature.as_bytes().to_vec().into());
796                SignatureScheme::Mldsa65
797            }
798            _ => return Self::default(),
799        };
800
801        message.set_scheme(scheme);
802        message
803    }
804}
805
806impl TryFrom<&MultisigMemberSignature> for sui_sdk_types::MultisigMemberSignature {
807    type Error = TryFromProtoError;
808
809    fn try_from(value: &MultisigMemberSignature) -> Result<Self, Self::Error> {
810        use sui_sdk_types::Ed25519Signature;
811        use sui_sdk_types::Secp256k1Signature;
812        use sui_sdk_types::Secp256r1Signature;
813
814        match value.scheme() {
815            SignatureScheme::Ed25519 => Self::Ed25519(
816                Ed25519Signature::from_bytes(value.signature()).map_err(|e| {
817                    TryFromProtoError::invalid(MultisigMemberSignature::SIGNATURE_FIELD, e)
818                })?,
819            ),
820            SignatureScheme::Secp256k1 => Self::Secp256k1(
821                Secp256k1Signature::from_bytes(value.signature()).map_err(|e| {
822                    TryFromProtoError::invalid(MultisigMemberSignature::SIGNATURE_FIELD, e)
823                })?,
824            ),
825            SignatureScheme::Secp256r1 => Self::Secp256r1(
826                Secp256r1Signature::from_bytes(value.signature()).map_err(|e| {
827                    TryFromProtoError::invalid(MultisigMemberSignature::SIGNATURE_FIELD, e)
828                })?,
829            ),
830            SignatureScheme::Zklogin => Self::ZkLogin(Box::new(
831                value
832                    .zklogin
833                    .as_ref()
834                    .ok_or_else(|| TryFromProtoError::missing("zklogin"))?
835                    .try_into()?,
836            )),
837            SignatureScheme::Passkey => Self::Passkey(
838                value
839                    .passkey
840                    .as_ref()
841                    .ok_or_else(|| TryFromProtoError::missing("passkey"))?
842                    .try_into()?,
843            ),
844            SignatureScheme::Mldsa65 => Self::MlDsa65(Box::new(
845                sui_sdk_types::MlDsa65Signature::from_bytes(value.signature()).map_err(|e| {
846                    TryFromProtoError::invalid(MultisigMemberSignature::SIGNATURE_FIELD, e)
847                })?,
848            )),
849            SignatureScheme::Multisig | SignatureScheme::Bls12381 => {
850                return Err(TryFromProtoError::invalid(
851                    MultisigMemberSignature::SCHEME_FIELD,
852                    "invalid MultisigMemberSignature scheme",
853                ));
854            }
855        }
856        .pipe(Ok)
857    }
858}
859
860//
861// MultisigAggregatedSignature
862//
863
864impl From<&sui_sdk_types::MultisigAggregatedSignature> for MultisigAggregatedSignature {
865    fn from(value: &sui_sdk_types::MultisigAggregatedSignature) -> Self {
866        Self {
867            signatures: value.signatures().iter().map(Into::into).collect(),
868            bitmap: Some(value.bitmap().into()),
869            legacy_bitmap: value.legacy_bitmap().map(|roaring| {
870                let mut bitmap = Vec::new();
871                roaring.serialize_into(&mut bitmap).unwrap();
872                bitmap.into()
873            }),
874            committee: Some(value.committee().into()),
875        }
876    }
877}
878
879impl TryFrom<&MultisigAggregatedSignature> for sui_sdk_types::MultisigAggregatedSignature {
880    type Error = TryFromProtoError;
881
882    fn try_from(value: &MultisigAggregatedSignature) -> Result<Self, Self::Error> {
883        let signatures = value
884            .signatures
885            .iter()
886            .map(TryInto::try_into)
887            .collect::<Result<_, _>>()?;
888        let bitmap = value
889            .bitmap
890            .ok_or_else(|| TryFromProtoError::missing("bitmap"))?
891            .try_into()
892            .map_err(|e| {
893                TryFromProtoError::invalid(MultisigAggregatedSignature::BITMAP_FIELD, e)
894            })?;
895        let committee = value
896            .committee
897            .as_ref()
898            .ok_or_else(|| TryFromProtoError::missing("committee"))?
899            .try_into()?;
900
901        let mut signature = Self::new(committee, signatures, bitmap);
902
903        if let Some(legacy_bitmap) = value.legacy_bitmap_opt() {
904            let legacy_bitmap =
905                sui_sdk_types::Bitmap::deserialize_from(legacy_bitmap).map_err(|e| {
906                    TryFromProtoError::invalid(MultisigAggregatedSignature::LEGACY_BITMAP_FIELD, e)
907                })?;
908            signature
909                .try_with_legacy_bitmap(legacy_bitmap)
910                .map_err(|e| {
911                    TryFromProtoError::invalid(MultisigAggregatedSignature::LEGACY_BITMAP_FIELD, e)
912                })?;
913        }
914
915        Ok(signature)
916    }
917}
918
919//
920// UserSignature
921//
922
923impl From<sui_sdk_types::UserSignature> for UserSignature {
924    fn from(value: sui_sdk_types::UserSignature) -> Self {
925        Self::merge_from(value, &FieldMaskTree::new_wildcard())
926    }
927}
928
929impl Merge<sui_sdk_types::UserSignature> for UserSignature {
930    fn merge(&mut self, source: sui_sdk_types::UserSignature, mask: &FieldMaskTree) {
931        use sui_sdk_types::UserSignature::*;
932        use user_signature::Signature;
933
934        if mask.contains(Self::BCS_FIELD.name) {
935            self.bcs = Some(Bcs {
936                name: Some("UserSignatureBytes".to_owned()),
937                value: Some(source.to_bytes().into()),
938            });
939        }
940
941        if mask.contains(Self::SCHEME_FIELD.name) {
942            self.scheme = Some(source.scheme().to_u8().into());
943        }
944
945        match source {
946            Simple(simple) if mask.contains(Self::SIMPLE_FIELD.name) => {
947                self.signature = Some(Signature::Simple(simple.into()));
948            }
949            Multisig(ref multisig) if mask.contains(Self::MULTISIG_FIELD.name) => {
950                self.signature = Some(Signature::Multisig(multisig.into()));
951            }
952            ZkLogin(zklogin) if mask.contains(Self::ZKLOGIN_FIELD.name) => {
953                self.signature = Some(Signature::Zklogin((*zklogin).into()));
954            }
955            Passkey(passkey) if mask.contains(Self::PASSKEY_FIELD.name) => {
956                self.signature = Some(Signature::Passkey(passkey.into()));
957            }
958            _ => {}
959        }
960    }
961}
962
963impl Merge<&UserSignature> for UserSignature {
964    fn merge(&mut self, source: &UserSignature, mask: &FieldMaskTree) {
965        use user_signature::Signature;
966
967        let UserSignature {
968            bcs,
969            scheme,
970            signature,
971        } = source;
972
973        if mask.contains(Self::BCS_FIELD.name) {
974            self.bcs = bcs.clone();
975        }
976
977        if mask.contains(Self::SCHEME_FIELD.name) {
978            self.scheme = *scheme;
979        }
980
981        if matches!(signature, Some(Signature::Simple(_))) && mask.contains(Self::SIMPLE_FIELD.name)
982            || matches!(signature, Some(Signature::Multisig(_)))
983                && mask.contains(Self::MULTISIG_FIELD.name)
984            || matches!(signature, Some(Signature::Zklogin(_)))
985                && mask.contains(Self::ZKLOGIN_FIELD.name)
986            || matches!(signature, Some(Signature::Passkey(_)))
987                && mask.contains(Self::PASSKEY_FIELD.name)
988        {
989            self.signature = signature.clone();
990        }
991    }
992}
993
994impl TryFrom<&UserSignature> for sui_sdk_types::UserSignature {
995    type Error = TryFromProtoError;
996
997    fn try_from(value: &UserSignature) -> Result<Self, Self::Error> {
998        use user_signature::Signature;
999
1000        if let Some(bcs) = &value.bcs {
1001            if let Ok(sig) = Self::from_bytes(bcs.value()) {
1002                return Ok(sig);
1003            } else {
1004                return bcs
1005                    .deserialize()
1006                    .map_err(|e| TryFromProtoError::invalid(UserSignature::BCS_FIELD, e));
1007            }
1008        }
1009
1010        let _scheme = value
1011            .scheme
1012            .ok_or_else(|| TryFromProtoError::missing("scheme"))?
1013            .pipe(SignatureScheme::try_from)
1014            .map_err(|e| TryFromProtoError::invalid(UserSignature::SCHEME_FIELD, e));
1015
1016        match &value.signature {
1017            Some(Signature::Simple(simple)) => Self::Simple(simple.try_into()?),
1018            Some(Signature::Multisig(multisig)) => Self::Multisig(multisig.try_into()?),
1019            Some(Signature::Zklogin(zklogin)) => Self::ZkLogin(Box::new(zklogin.try_into()?)),
1020            Some(Signature::Passkey(passkey)) => Self::Passkey(passkey.try_into()?),
1021            None => {
1022                return Err(TryFromProtoError::invalid(
1023                    "signature",
1024                    "invalid or unknown signature scheme",
1025                ));
1026            }
1027        }
1028        .pipe(Ok)
1029    }
1030}
1031
1032#[cfg(test)]
1033mod tests {
1034    use super::*;
1035
1036    fn legacy_bitmap_bytes(indices: &[u32]) -> prost::bytes::Bytes {
1037        let bitmap: sui_sdk_types::Bitmap = indices.iter().copied().collect();
1038        let mut bytes = Vec::new();
1039        bitmap.serialize_into(&mut bytes).unwrap();
1040        bytes.into()
1041    }
1042
1043    /// A proto multisig whose single-member committee has signed, per
1044    /// `bitmap`, with no `legacy_bitmap` set yet.
1045    fn single_member_multisig(
1046        public_key: sui_sdk_types::MultisigMemberPublicKey,
1047    ) -> MultisigAggregatedSignature {
1048        let committee = sui_sdk_types::MultisigCommittee::new(
1049            vec![sui_sdk_types::MultisigMember::new(public_key, 1)],
1050            1,
1051        );
1052        let signature = sui_sdk_types::MultisigAggregatedSignature::new(committee, Vec::new(), 0b1);
1053        MultisigAggregatedSignature::from(&signature)
1054    }
1055
1056    fn assert_invalid_legacy_bitmap(proto: &MultisigAggregatedSignature, description: &str) {
1057        let err = sui_sdk_types::MultisigAggregatedSignature::try_from(proto).unwrap_err();
1058        let violation = err.field_violation();
1059        assert_eq!(
1060            violation.field,
1061            MultisigAggregatedSignature::LEGACY_BITMAP_FIELD.name
1062        );
1063        assert_eq!(violation.description, description);
1064    }
1065
1066    // Regression test: a `legacy_bitmap` on a committee with a member that
1067    // the legacy format cannot encode used to convert successfully, and the
1068    // resulting signature then panicked on its first `to_bytes()`.
1069    #[test]
1070    fn legacy_bitmap_with_unrepresentable_member_is_rejected() {
1071        let public_key = sui_sdk_types::MultisigMemberPublicKey::MlDsa65(Box::new(
1072            sui_sdk_types::MlDsa65PublicKey::new([0; sui_sdk_types::MlDsa65PublicKey::LENGTH]),
1073        ));
1074        let mut proto = single_member_multisig(public_key);
1075        proto.legacy_bitmap = Some(legacy_bitmap_bytes(&[0]));
1076
1077        assert_invalid_legacy_bitmap(
1078            &proto,
1079            "mldsa65 member is not representable in legacy multisig",
1080        );
1081    }
1082
1083    // Regression test: `bitmap` and `legacy_bitmap` used to be accepted
1084    // even when they named different signers, so `bitmap()` and
1085    // `to_bytes()` disagreed on who signed.
1086    #[test]
1087    fn legacy_bitmap_must_match_bitmap() {
1088        let public_key = sui_sdk_types::MultisigMemberPublicKey::Ed25519(
1089            sui_sdk_types::Ed25519PublicKey::new([1; sui_sdk_types::Ed25519PublicKey::LENGTH]),
1090        );
1091        let mut proto = single_member_multisig(public_key);
1092
1093        proto.legacy_bitmap = Some(legacy_bitmap_bytes(&[1]));
1094        assert_invalid_legacy_bitmap(&proto, "bitmap does not match legacy_bitmap");
1095
1096        proto.legacy_bitmap = Some(legacy_bitmap_bytes(&[0]));
1097        let signature = sui_sdk_types::MultisigAggregatedSignature::try_from(&proto).unwrap();
1098        let expected: sui_sdk_types::Bitmap = [0].into_iter().collect();
1099        assert_eq!(signature.legacy_bitmap(), Some(&expected));
1100
1101        let signature = sui_sdk_types::UserSignature::Multisig(signature);
1102        let bytes = signature.to_bytes();
1103        assert_eq!(
1104            sui_sdk_types::UserSignature::from_bytes(&bytes).unwrap(),
1105            signature
1106        );
1107    }
1108}