accumulate_client/runtime/
signing.rs1use crate::generated::signatures::Signature;
3use crate::generated::signatures::{DelegatedSignature, SignatureSet};
4
5#[derive(thiserror::Error, Debug)]
6pub enum SigRuntimeError {
7 #[error("delegation depth exceeded (max 5)")]
8 DelegationDepthExceeded,
9 #[error("invalid signature set threshold")]
10 InvalidSignatureSetThreshold,
11 #[error("verification failed")]
12 VerificationFailed,
13}
14
15pub fn delegated_depth(sig: &Signature) -> usize {
19 match sig {
20 Signature::Delegated(inner) => 1 + delegated_depth(&inner.signature),
21 _ => 0,
22 }
23}
24
25pub fn enforce_delegated_depth(sig: &Signature) -> Result<(), SigRuntimeError> {
27 if delegated_depth(sig) > 5 {
28 Err(SigRuntimeError::DelegationDepthExceeded)
29 } else {
30 Ok(())
31 }
32}
33
34impl DelegatedSignature {
35 pub fn new_enforced(signature: Box<Signature>, delegator: String) -> Result<Self, SigRuntimeError> {
37 let wrapper = Signature::Delegated(DelegatedSignature {
38 signature: signature.clone(),
39 delegator: delegator.clone()
40 });
41 enforce_delegated_depth(&wrapper)?;
42 Ok(DelegatedSignature { signature, delegator })
43 }
44}
45
46#[derive(Debug, Clone)]
50pub struct SignatureSetWithThreshold {
51 pub inner: SignatureSet,
52 pub threshold: u32,
53}
54
55impl SignatureSetWithThreshold {
56 pub fn new(inner: SignatureSet, threshold: u32) -> Result<Self, SigRuntimeError> {
57 if threshold == 0 || (threshold as usize) > inner.signatures.len() {
58 return Err(SigRuntimeError::InvalidSignatureSetThreshold);
59 }
60 Ok(Self { inner, threshold })
61 }
62}
63
64pub fn count_valid_sigs(sigs: &[Box<Signature>], message: &[u8]) -> usize {
67 sigs.iter()
68 .filter(|s| {
69 use crate::generated::signatures::AccSignature;
71 match s.as_ref() {
72 Signature::ED25519(sig) => sig.verify(message).unwrap_or(false),
73 Signature::LegacyED25519(sig) => sig.verify(message).unwrap_or(false),
74 Signature::RCD1(sig) => sig.verify(message).unwrap_or(false),
75 Signature::BTC(sig) => sig.verify(message).unwrap_or(false),
76 Signature::BTCLegacy(sig) => sig.verify(message).unwrap_or(false),
77 Signature::ETH(sig) => sig.verify(message).unwrap_or(false),
78 Signature::RsaSha256(sig) => sig.verify(message).unwrap_or(false),
79 Signature::EcdsaSha256(sig) => sig.verify(message).unwrap_or(false),
80 Signature::TypedData(sig) => sig.verify(message).unwrap_or(false),
81 Signature::Receipt(sig) => sig.verify(message).unwrap_or(false),
82 Signature::Partition(sig) => sig.verify(message).unwrap_or(false),
83 Signature::Set(sig) => sig.verify(message).unwrap_or(false),
84 Signature::Remote(sig) => sig.verify(message).unwrap_or(false),
85 Signature::Delegated(sig) => sig.verify(message).unwrap_or(false),
86 Signature::Internal(sig) => sig.verify(message).unwrap_or(false),
87 Signature::Authority(sig) => sig.verify(message).unwrap_or(false),
88 }
89 })
90 .count()
91}
92
93pub fn evaluate_signature_set(set: &SignatureSetWithThreshold, message: &[u8]) -> Result<bool, SigRuntimeError> {
97 let n = set.inner.signatures.len();
98 if set.threshold == 0 || (set.threshold as usize) > n {
99 return Err(SigRuntimeError::InvalidSignatureSetThreshold);
100 }
101 let valid = count_valid_sigs(&set.inner.signatures, message) as u32;
102 Ok(valid >= set.threshold)
103}