oasis_runtime_sdk/crypto/multisig/
mod.rs1use thiserror::Error;
2
3use crate::crypto::signature::{PublicKey, Signature};
4
5#[cfg(test)]
6mod test;
7
8#[derive(Error, Debug)]
10pub enum Error {
11 #[error("invalid config")]
12 InvalidConfig,
13 #[error("invalid signature set")]
14 InvalidSignatureSet,
15 #[error("insufficient weight")]
16 InsufficientWeight,
17}
18
19#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
21#[cbor(no_default)]
22pub struct Signer {
23 pub public_key: PublicKey,
25 pub weight: u64,
27}
28
29pub type SignatureSet = [Option<Signature>];
32pub type SignatureSetOwned = Vec<Option<Signature>>;
34
35#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
39pub struct Config {
40 pub signers: Vec<Signer>,
42 pub threshold: u64,
44}
45
46impl Config {
47 pub fn validate_basic(&self) -> Result<(), Error> {
50 if self.threshold == 0 {
51 return Err(Error::InvalidConfig);
52 }
53 let mut total: u64 = 0;
54 for (i, signer) in self.signers.iter().enumerate() {
55 if self
56 .signers
57 .iter()
58 .take(i)
59 .any(|other_signer| signer.public_key == other_signer.public_key)
60 {
61 return Err(Error::InvalidConfig);
62 }
63 if signer.weight == 0 {
64 return Err(Error::InvalidConfig);
65 }
66 total = total
67 .checked_add(signer.weight)
68 .ok_or(Error::InvalidConfig)?;
69 }
70 if total < self.threshold {
71 return Err(Error::InvalidConfig);
72 }
73 Ok(())
74 }
75
76 pub fn batch(
79 &self,
80 signature_set: &SignatureSet,
81 ) -> Result<(Vec<PublicKey>, Vec<Signature>), Error> {
82 self.validate_basic()?;
83 if signature_set.len() != self.signers.len() {
84 return Err(Error::InvalidSignatureSet);
85 }
86 let mut total = 0;
87 let mut public_keys = vec![];
88 let mut signatures = vec![];
89 for (signer, signature_o) in self.signers.iter().zip(signature_set.iter()) {
90 if let Some(signature) = signature_o {
91 total += signer.weight;
92 public_keys.push(signer.public_key.clone());
93 signatures.push(signature.clone());
94 }
95 }
96 if total < self.threshold {
97 return Err(Error::InsufficientWeight);
98 }
99 Ok((public_keys, signatures))
100 }
101}