blvm_sdk/governance/
multisig.rs1use std::collections::HashSet;
6
7use crate::governance::error::{GovernanceError, GovernanceResult};
8use crate::governance::{PublicKey, Signature};
9
10#[derive(Debug, Clone)]
12pub struct Multisig {
13 threshold: usize,
14 total: usize,
15 public_keys: Vec<PublicKey>,
16}
17
18impl Multisig {
19 pub fn new(
21 threshold: usize,
22 total: usize,
23 public_keys: Vec<PublicKey>,
24 ) -> GovernanceResult<Self> {
25 if threshold == 0 {
26 return Err(GovernanceError::InvalidThreshold { threshold, total });
27 }
28
29 if threshold > total {
30 return Err(GovernanceError::InvalidThreshold { threshold, total });
31 }
32
33 if public_keys.len() != total {
34 return Err(GovernanceError::InvalidMultisig(format!(
35 "Expected {} public keys, got {}",
36 total,
37 public_keys.len()
38 )));
39 }
40
41 let unique_keys: HashSet<_> = public_keys.iter().collect();
43 if unique_keys.len() != public_keys.len() {
44 return Err(GovernanceError::InvalidMultisig(
45 "Duplicate public keys not allowed".to_string(),
46 ));
47 }
48
49 Ok(Self {
50 threshold,
51 total,
52 public_keys,
53 })
54 }
55
56 pub fn verify(&self, message: &[u8], signatures: &[Signature]) -> GovernanceResult<bool> {
58 if signatures.len() < self.threshold {
59 return Err(GovernanceError::InsufficientSignatures {
60 got: signatures.len(),
61 need: self.threshold,
62 });
63 }
64
65 let valid_signatures = self.collect_valid_signatures(message, signatures)?;
66 Ok(valid_signatures.len() >= self.threshold)
67 }
68
69 pub fn collect_valid_signatures(
71 &self,
72 message: &[u8],
73 signatures: &[Signature],
74 ) -> GovernanceResult<Vec<usize>> {
75 let mut valid_indices = Vec::new();
76
77 for signature in signatures.iter() {
78 for (j, public_key) in self.public_keys.iter().enumerate() {
80 if crate::governance::verify_signature(signature, message, public_key)? {
81 valid_indices.push(j);
82 break;
83 }
84 }
85 }
86
87 Ok(valid_indices)
88 }
89
90 pub fn threshold(&self) -> usize {
92 self.threshold
93 }
94
95 pub fn total(&self) -> usize {
97 self.total
98 }
99
100 pub fn public_keys(&self) -> &[PublicKey] {
102 &self.public_keys
103 }
104
105 pub fn is_valid_signature(
107 &self,
108 signature: &Signature,
109 message: &[u8],
110 ) -> GovernanceResult<Option<usize>> {
111 for (i, public_key) in self.public_keys.iter().enumerate() {
112 if crate::governance::verify_signature(signature, message, public_key)? {
113 return Ok(Some(i));
114 }
115 }
116 Ok(None)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::governance::GovernanceKeypair;
124
125 #[test]
126 fn test_multisig_creation() {
127 let keypairs: Vec<_> = (0..5)
128 .map(|_| GovernanceKeypair::generate().unwrap())
129 .collect();
130 let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key()).collect();
131
132 let multisig = Multisig::new(3, 5, public_keys).unwrap();
133 assert_eq!(multisig.threshold(), 3);
134 assert_eq!(multisig.total(), 5);
135 }
136
137 #[test]
138 fn test_invalid_threshold() {
139 let keypairs: Vec<_> = (0..5)
140 .map(|_| GovernanceKeypair::generate().unwrap())
141 .collect();
142 let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key()).collect();
143
144 let result = Multisig::new(6, 5, public_keys.clone());
146 assert!(result.is_err());
147
148 let result = Multisig::new(0, 5, public_keys);
150 assert!(result.is_err());
151 }
152
153 #[test]
154 fn test_multisig_verification() {
155 let keypairs: Vec<_> = (0..5)
156 .map(|_| GovernanceKeypair::generate().unwrap())
157 .collect();
158 let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key()).collect();
159
160 let multisig = Multisig::new(3, 5, public_keys).unwrap();
161 let message = b"test message";
162
163 let signatures: Vec<_> = keypairs[0..3]
165 .iter()
166 .map(|kp| crate::sign_message(&kp.secret_key, message).unwrap())
167 .collect();
168
169 let result = multisig.verify(message, &signatures).unwrap();
170 assert!(result);
171 }
172
173 #[test]
174 fn test_insufficient_signatures() {
175 let keypairs: Vec<_> = (0..5)
176 .map(|_| GovernanceKeypair::generate().unwrap())
177 .collect();
178 let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key()).collect();
179
180 let multisig = Multisig::new(3, 5, public_keys).unwrap();
181 let message = b"test message";
182
183 let signatures: Vec<_> = keypairs[0..2]
185 .iter()
186 .map(|kp| crate::sign_message(&kp.secret_key, message).unwrap())
187 .collect();
188
189 let result = multisig.verify(message, &signatures);
190 assert!(result.is_err());
191 }
192
193 #[test]
194 fn test_duplicate_public_keys() {
195 let keypair = GovernanceKeypair::generate().unwrap();
196 let public_key = keypair.public_key();
197
198 let public_keys = vec![public_key.clone(), public_key];
200
201 let result = Multisig::new(2, 2, public_keys);
202 assert!(result.is_err());
203 }
204}