1use super::{
6 Ed25519PublicKey, Ed25519Signature, Secp256k1PublicKey, Secp256k1Signature, Secp256r1PublicKey,
7 Secp256r1Signature, SignatureScheme,
8 zklogin::{ZkLoginAuthenticator, ZkLoginPublicIdentifier},
9};
10
11pub type WeightUnit = u8;
12pub type ThresholdUnit = u16;
13pub type BitmapUnit = u16;
14
15const MAX_COMMITTEE_SIZE: usize = 10;
16#[derive(Clone, Debug, PartialEq, Eq)]
48#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
49pub enum MultisigMemberPublicKey {
50 Ed25519(Ed25519PublicKey),
51 Secp256k1(Secp256k1PublicKey),
52 Secp256r1(Secp256r1PublicKey),
53 ZkLogin(ZkLoginPublicIdentifier),
54}
55
56impl MultisigMemberPublicKey {
57 crate::def_is_as_into_opt!(
58 Ed25519(Ed25519PublicKey),
59 Secp256k1(Secp256k1PublicKey),
60 Secp256r1(Secp256r1PublicKey),
61 ZkLogin as zklogin(ZkLoginPublicIdentifier),
62 );
63}
64
65#[derive(Clone, Debug, PartialEq, Eq)]
83#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
85#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
86pub struct MultisigMember {
87 public_key: MultisigMemberPublicKey,
88 weight: WeightUnit,
89}
90
91impl MultisigMember {
92 pub fn new(public_key: MultisigMemberPublicKey, weight: WeightUnit) -> Self {
94 Self { public_key, weight }
95 }
96
97 pub fn public_key(&self) -> &MultisigMemberPublicKey {
99 &self.public_key
100 }
101
102 pub fn weight(&self) -> WeightUnit {
104 self.weight
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
133#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
134pub struct MultisigCommittee {
135 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=10).lift()))]
137 members: Vec<MultisigMember>,
138 threshold: ThresholdUnit,
141}
142
143impl MultisigCommittee {
144 pub fn new(members: Vec<MultisigMember>, threshold: ThresholdUnit) -> Self {
150 Self { members, threshold }
151 }
152
153 pub fn members(&self) -> &[MultisigMember] {
155 &self.members
156 }
157
158 pub fn threshold(&self) -> ThresholdUnit {
161 self.threshold
162 }
163
164 pub fn scheme(&self) -> SignatureScheme {
166 SignatureScheme::Multisig
167 }
168
169 pub fn is_valid(&self) -> bool {
180 self.threshold != 0
181 && !self.members.is_empty()
182 && self.members.len() <= MAX_COMMITTEE_SIZE
183 && !self.members.iter().any(|member| member.weight == 0)
184 && self
185 .members
186 .iter()
187 .map(|member| member.weight as ThresholdUnit)
188 .sum::<ThresholdUnit>()
189 >= self.threshold
190 && !self.members.iter().enumerate().any(|(i, member)| {
191 self.members
192 .iter()
193 .skip(i + 1)
194 .any(|m| member.public_key == m.public_key)
195 })
196 }
197}
198
199#[derive(Debug, Clone)]
225#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
226#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
227pub struct MultisigAggregatedSignature {
228 #[cfg_attr(feature = "proptest", any(proptest::collection::size_range(0..=10).lift()))]
233 signatures: Vec<MultisigMemberSignature>,
234 bitmap: BitmapUnit,
237 committee: MultisigCommittee,
240}
241
242impl MultisigAggregatedSignature {
243 pub fn new(
251 committee: MultisigCommittee,
252 signatures: Vec<MultisigMemberSignature>,
253 bitmap: BitmapUnit,
254 ) -> Self {
255 Self {
256 signatures,
257 bitmap,
258 committee,
259 }
260 }
261
262 pub fn signatures(&self) -> &[MultisigMemberSignature] {
264 &self.signatures
265 }
266
267 pub fn bitmap(&self) -> BitmapUnit {
270 self.bitmap
271 }
272
273 pub fn committee(&self) -> &MultisigCommittee {
274 &self.committee
275 }
276}
277
278impl PartialEq for MultisigAggregatedSignature {
279 fn eq(&self, other: &Self) -> bool {
280 self.bitmap == other.bitmap
281 && self.signatures == other.signatures
282 && self.committee == other.committee
283 }
284}
285
286impl Eq for MultisigAggregatedSignature {}
287
288#[derive(Debug, Clone, PartialEq, Eq)]
306#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
307pub enum MultisigMemberSignature {
308 Ed25519(Ed25519Signature),
309 Secp256k1(Secp256k1Signature),
310 Secp256r1(Secp256r1Signature),
311 ZkLogin(Box<ZkLoginAuthenticator>),
312}
313
314impl MultisigMemberSignature {
315 crate::def_is_as_into_opt!(
316 Ed25519(Ed25519Signature),
317 Secp256k1(Secp256k1Signature),
318 Secp256r1(Secp256r1Signature),
319 ZkLogin as zklogin(Box<ZkLoginAuthenticator>)
320 );
321}
322
323#[cfg(feature = "serde")]
324#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
325mod serialization {
326 use std::borrow::Cow;
327
328 use serde::{Deserialize, Deserializer, Serialize, Serializer};
329 use serde_with::{Bytes, DeserializeAs};
330
331 use super::*;
332 use crate::{
333 Ed25519PublicKey, Secp256k1PublicKey, Secp256r1PublicKey, SignatureScheme,
334 crypto::SignatureFromBytesError,
335 };
336
337 #[derive(serde::Deserialize)]
338 pub struct Multisig {
339 signatures: Vec<MultisigMemberSignature>,
340 bitmap: BitmapUnit,
341 committee: MultisigCommittee,
342 }
343
344 #[derive(serde::Serialize)]
345 pub struct MultisigRef<'a> {
346 signatures: &'a [MultisigMemberSignature],
347 bitmap: BitmapUnit,
348 committee: &'a MultisigCommittee,
349 }
350
351 #[derive(serde::Deserialize)]
352 struct ReadableMultisigAggregatedSignature {
353 signatures: Vec<MultisigMemberSignature>,
354 bitmap: BitmapUnit,
355 committee: MultisigCommittee,
356 }
357
358 #[derive(serde::Serialize)]
359 struct ReadableMultisigAggregatedSignatureRef<'a> {
360 signatures: &'a [MultisigMemberSignature],
361 bitmap: BitmapUnit,
362 committee: &'a MultisigCommittee,
363 }
364
365 impl Serialize for MultisigAggregatedSignature {
366 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
367 where
368 S: Serializer,
369 {
370 if serializer.is_human_readable() {
371 let readable = ReadableMultisigAggregatedSignatureRef {
372 signatures: &self.signatures,
373 bitmap: self.bitmap,
374 committee: &self.committee,
375 };
376 readable.serialize(serializer)
377 } else {
378 let bytes = self.to_bytes();
379 serializer.serialize_bytes(&bytes)
380 }
381 }
382 }
383
384 impl<'de> Deserialize<'de> for MultisigAggregatedSignature {
385 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
386 where
387 D: Deserializer<'de>,
388 {
389 if deserializer.is_human_readable() {
390 let readable = ReadableMultisigAggregatedSignature::deserialize(deserializer)?;
391 Ok(Self {
392 signatures: readable.signatures,
393 bitmap: readable.bitmap,
394 committee: readable.committee,
395 })
396 } else {
397 let bytes: Cow<'de, [u8]> = Bytes::deserialize_as(deserializer)?;
398 Self::from_serialized_bytes(bytes).map_err(serde::de::Error::custom)
399 }
400 }
401 }
402
403 impl MultisigAggregatedSignature {
404 pub(crate) fn to_bytes(&self) -> Vec<u8> {
405 let mut buf = Vec::new();
406 buf.push(SignatureScheme::Multisig as u8);
407
408 let multisig = MultisigRef {
409 signatures: &self.signatures,
410 bitmap: self.bitmap,
411 committee: &self.committee,
412 };
413 bcs::serialize_into(&mut buf, &multisig).expect("serialization cannot fail");
414 buf
415 }
416
417 pub fn from_serialized_bytes(
418 bytes: impl AsRef<[u8]>,
419 ) -> Result<Self, SignatureFromBytesError> {
420 let bytes = bytes.as_ref();
421 let flag =
422 SignatureScheme::from_byte(*bytes.first().ok_or_else(|| {
423 SignatureFromBytesError::new("missing signature scheme flag")
424 })?)
425 .map_err(SignatureFromBytesError::new)?;
426 if flag != SignatureScheme::Multisig {
427 return Err(SignatureFromBytesError::new("invalid multisig flag"));
428 }
429 let bcs_bytes = &bytes[1..];
430
431 if let Ok(multisig) = bcs::from_bytes::<Multisig>(bcs_bytes) {
432 Ok(Self {
433 signatures: multisig.signatures,
434 bitmap: multisig.bitmap,
435 committee: multisig.committee,
436 })
437 } else {
438 Err(SignatureFromBytesError::new("invalid multisig"))
439 }
440 }
441 }
442
443 #[derive(serde::Serialize, serde::Deserialize)]
444 enum MemberPublicKey {
445 Ed25519(Ed25519PublicKey),
446 Secp256k1(Secp256k1PublicKey),
447 Secp256r1(Secp256r1PublicKey),
448 ZkLogin(ZkLoginPublicIdentifier),
449 }
450
451 #[derive(serde::Serialize, serde::Deserialize)]
452 #[serde(tag = "scheme", rename_all = "lowercase")]
453 #[serde(rename = "MultisigMemberPublicKey")]
454 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
455 enum ReadableMemberPublicKey {
456 Ed25519 { public_key: Ed25519PublicKey },
457 Secp256k1 { public_key: Secp256k1PublicKey },
458 Secp256r1 { public_key: Secp256r1PublicKey },
459 ZkLogin(ZkLoginPublicIdentifier),
460 }
461
462 #[cfg(feature = "schemars")]
463 impl schemars::JsonSchema for MultisigMemberPublicKey {
464 fn schema_name() -> String {
465 ReadableMemberPublicKey::schema_name()
466 }
467
468 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
469 ReadableMemberPublicKey::json_schema(gen)
470 }
471 }
472
473 impl Serialize for MultisigMemberPublicKey {
474 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
475 where
476 S: Serializer,
477 {
478 if serializer.is_human_readable() {
479 let readable = match self {
480 MultisigMemberPublicKey::Ed25519(public_key) => {
481 ReadableMemberPublicKey::Ed25519 {
482 public_key: *public_key,
483 }
484 }
485 MultisigMemberPublicKey::Secp256k1(public_key) => {
486 ReadableMemberPublicKey::Secp256k1 {
487 public_key: *public_key,
488 }
489 }
490 MultisigMemberPublicKey::Secp256r1(public_key) => {
491 ReadableMemberPublicKey::Secp256r1 {
492 public_key: *public_key,
493 }
494 }
495 MultisigMemberPublicKey::ZkLogin(public_id) => {
496 ReadableMemberPublicKey::ZkLogin(public_id.clone())
497 }
498 };
499 readable.serialize(serializer)
500 } else {
501 let binary = match self {
502 MultisigMemberPublicKey::Ed25519(public_key) => {
503 MemberPublicKey::Ed25519(*public_key)
504 }
505 MultisigMemberPublicKey::Secp256k1(public_key) => {
506 MemberPublicKey::Secp256k1(*public_key)
507 }
508 MultisigMemberPublicKey::Secp256r1(public_key) => {
509 MemberPublicKey::Secp256r1(*public_key)
510 }
511 MultisigMemberPublicKey::ZkLogin(public_id) => {
512 MemberPublicKey::ZkLogin(public_id.clone())
513 }
514 };
515 binary.serialize(serializer)
516 }
517 }
518 }
519
520 impl<'de> Deserialize<'de> for MultisigMemberPublicKey {
521 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
522 where
523 D: Deserializer<'de>,
524 {
525 if deserializer.is_human_readable() {
526 let readable = ReadableMemberPublicKey::deserialize(deserializer)?;
527 Ok(match readable {
528 ReadableMemberPublicKey::Ed25519 { public_key } => Self::Ed25519(public_key),
529 ReadableMemberPublicKey::Secp256k1 { public_key } => {
530 Self::Secp256k1(public_key)
531 }
532 ReadableMemberPublicKey::Secp256r1 { public_key } => {
533 Self::Secp256r1(public_key)
534 }
535 ReadableMemberPublicKey::ZkLogin(public_id) => Self::ZkLogin(public_id),
536 })
537 } else {
538 let binary = MemberPublicKey::deserialize(deserializer)?;
539 Ok(match binary {
540 MemberPublicKey::Ed25519(public_key) => Self::Ed25519(public_key),
541 MemberPublicKey::Secp256k1(public_key) => Self::Secp256k1(public_key),
542 MemberPublicKey::Secp256r1(public_key) => Self::Secp256r1(public_key),
543 MemberPublicKey::ZkLogin(public_id) => Self::ZkLogin(public_id),
544 })
545 }
546 }
547 }
548
549 #[derive(serde::Serialize, serde::Deserialize)]
550 enum MemberSignature {
551 Ed25519(Ed25519Signature),
552 Secp256k1(Secp256k1Signature),
553 Secp256r1(Secp256r1Signature),
554 ZkLogin(Box<ZkLoginAuthenticator>),
555 }
556
557 #[derive(serde::Serialize, serde::Deserialize)]
558 #[serde(tag = "scheme", rename_all = "lowercase")]
559 #[serde(rename = "MultisigMemberSignature")]
560 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
561 enum ReadableMemberSignature {
562 Ed25519 { signature: Ed25519Signature },
563 Secp256k1 { signature: Secp256k1Signature },
564 Secp256r1 { signature: Secp256r1Signature },
565 ZkLogin(Box<ZkLoginAuthenticator>),
566 }
567
568 #[cfg(feature = "schemars")]
569 impl schemars::JsonSchema for MultisigMemberSignature {
570 fn schema_name() -> String {
571 ReadableMemberSignature::schema_name()
572 }
573
574 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
575 ReadableMemberSignature::json_schema(gen)
576 }
577 }
578
579 impl Serialize for MultisigMemberSignature {
580 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
581 where
582 S: Serializer,
583 {
584 if serializer.is_human_readable() {
585 let readable = match self {
586 MultisigMemberSignature::Ed25519(signature) => {
587 ReadableMemberSignature::Ed25519 {
588 signature: *signature,
589 }
590 }
591 MultisigMemberSignature::Secp256k1(signature) => {
592 ReadableMemberSignature::Secp256k1 {
593 signature: *signature,
594 }
595 }
596 MultisigMemberSignature::Secp256r1(signature) => {
597 ReadableMemberSignature::Secp256r1 {
598 signature: *signature,
599 }
600 }
601 MultisigMemberSignature::ZkLogin(authenticator) => {
602 ReadableMemberSignature::ZkLogin(authenticator.clone())
603 }
604 };
605 readable.serialize(serializer)
606 } else {
607 let binary = match self {
608 MultisigMemberSignature::Ed25519(signature) => {
609 MemberSignature::Ed25519(*signature)
610 }
611 MultisigMemberSignature::Secp256k1(signature) => {
612 MemberSignature::Secp256k1(*signature)
613 }
614 MultisigMemberSignature::Secp256r1(signature) => {
615 MemberSignature::Secp256r1(*signature)
616 }
617 MultisigMemberSignature::ZkLogin(authenticator) => {
618 MemberSignature::ZkLogin(authenticator.clone())
619 }
620 };
621 binary.serialize(serializer)
622 }
623 }
624 }
625
626 impl<'de> Deserialize<'de> for MultisigMemberSignature {
627 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
628 where
629 D: Deserializer<'de>,
630 {
631 if deserializer.is_human_readable() {
632 let readable = ReadableMemberSignature::deserialize(deserializer)?;
633 Ok(match readable {
634 ReadableMemberSignature::Ed25519 { signature } => Self::Ed25519(signature),
635 ReadableMemberSignature::Secp256k1 { signature } => Self::Secp256k1(signature),
636 ReadableMemberSignature::Secp256r1 { signature } => Self::Secp256r1(signature),
637 ReadableMemberSignature::ZkLogin(authenticator) => Self::ZkLogin(authenticator),
638 })
639 } else {
640 let binary = MemberSignature::deserialize(deserializer)?;
641 Ok(match binary {
642 MemberSignature::Ed25519(signature) => Self::Ed25519(signature),
643 MemberSignature::Secp256k1(signature) => Self::Secp256k1(signature),
644 MemberSignature::Secp256r1(signature) => Self::Secp256r1(signature),
645 MemberSignature::ZkLogin(authenticator) => Self::ZkLogin(authenticator),
646 })
647 }
648 }
649 }
650}