1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use algonaut_crypto::Ed25519PublicKey;
use algonaut_crypto::Signature;
use serde::{Deserialize, Serialize, Serializer};
use std::fmt::Debug;
pub const MULTISIG_VERSION: u8 = 1;
#[derive(Default, Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct MultisigSignature {
#[serde(rename = "subsig")]
pub subsigs: Vec<MultisigSubsig>,
#[serde(rename = "thr")]
pub threshold: u8,
#[serde(rename = "v")]
pub version: u8,
}
impl MultisigSignature {
pub fn verify(&self, message: &[u8]) -> bool {
if self.version != MULTISIG_VERSION || self.threshold == 0 || self.subsigs.is_empty() {
return false;
}
if self.threshold as usize > self.subsigs.len() {
return false;
}
self.verify_subsigs(message)
}
fn verify_subsigs(&self, message: &[u8]) -> bool {
self.subsigs
.iter()
.filter(|subsig| {
subsig
.sig
.map(|sig| subsig.key.verify(message, &sig))
.unwrap_or(false)
})
.count()
== self.threshold as usize
}
}
impl Serialize for MultisigSignature {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap;
let mut state = serializer.serialize_map(Some(3))?;
state.serialize_entry("subsig", &self.subsigs)?;
state.serialize_entry("thr", &self.threshold)?;
state.serialize_entry("v", &self.version)?;
state.end()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct MultisigSubsig {
#[serde(rename = "pk")]
pub key: Ed25519PublicKey,
#[serde(rename = "s")]
pub sig: Option<Signature>,
}
impl Serialize for MultisigSubsig {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap;
let len = if self.sig.is_some() { 2 } else { 1 };
let mut state = serializer.serialize_map(Some(len))?;
state.serialize_entry("pk", &self.key)?;
if let Some(sig) = &self.sig {
state.serialize_entry("s", sig)?;
}
state.end()
}
}