1use super::*;
2use crate::field::FieldMaskTree;
3use crate::merge::Merge;
4use crate::proto::TryFromProtoError;
5use tap::Pipe;
6
7impl 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
52impl 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
84impl 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
115impl 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
158impl 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
224impl 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
256impl 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
294impl 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
345impl 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
389impl 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
428impl 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
452impl 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
560impl 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
604impl 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
699impl 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
731impl 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
763impl 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
860impl 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
919impl 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 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 #[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 #[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}