1pub mod dkg;
20pub mod frost;
21pub mod group;
22
23pub use self::group::*;
24
25use crate::quantum_crypto::types::*;
26use serde::{Deserialize, Serialize};
27use std::collections::HashMap;
28use std::time::SystemTime;
29use thiserror::Error;
30
31#[derive(Debug, Error)]
33pub enum ThresholdError {
34 #[error("Invalid threshold parameters: {0}")]
35 InvalidParameters(String),
36
37 #[error("Insufficient participants: need {required}, have {available}")]
38 InsufficientParticipants { required: u16, available: u16 },
39
40 #[error("Invalid share: {0}")]
41 InvalidShare(String),
42
43 #[error("DKG ceremony failed: {0}")]
44 DkgFailed(String),
45
46 #[error("Signature aggregation failed: {0}")]
47 AggregationFailed(String),
48
49 #[error("Group operation failed: {0}")]
50 GroupOperationFailed(String),
51
52 #[error("Consensus failed: {0}")]
53 ConsensusFailed(String),
54
55 #[error("Participant not found: {0}")]
56 ParticipantNotFound(ParticipantId),
57
58 #[error("Unauthorized operation: {0}")]
59 Unauthorized(String),
60}
61
62pub type Result<T> = std::result::Result<T, ThresholdError>;
64
65pub type ThresholdSignature = Vec<u8>;
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ThresholdGroup {
71 pub group_id: GroupId,
73
74 pub threshold: u16,
76
77 pub participants: u16,
79
80 pub frost_group_key: FrostGroupPublicKey,
82
83 pub active_participants: Vec<ParticipantInfo>,
85
86 pub pending_participants: Vec<ParticipantInfo>,
88
89 pub version: u64,
91
92 pub metadata: GroupMetadata,
94
95 pub audit_log: Vec<GroupAuditEntry>,
97
98 pub created_at: SystemTime,
100
101 pub last_updated: SystemTime,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct ParticipantInfo {
108 pub participant_id: ParticipantId,
110
111 pub public_key: Vec<u8>, pub frost_share_commitment: FrostCommitment,
116
117 pub role: ParticipantRole,
119
120 pub status: ParticipantStatus,
122
123 pub joined_at: SystemTime,
125
126 pub metadata: HashMap<String, String>,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
132pub enum ParticipantRole {
133 Leader { permissions: LeaderPermissions },
135
136 Member { permissions: MemberPermissions },
138
139 Observer,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
145pub struct LeaderPermissions {
146 pub can_add_participants: bool,
147 pub can_remove_participants: bool,
148 pub can_update_threshold: bool,
149 pub can_initiate_refresh: bool,
150 pub can_assign_roles: bool,
151 pub can_create_subgroups: bool,
152}
153
154impl Default for LeaderPermissions {
155 fn default() -> Self {
156 Self {
157 can_add_participants: true,
158 can_remove_participants: true,
159 can_update_threshold: true,
160 can_initiate_refresh: true,
161 can_assign_roles: true,
162 can_create_subgroups: true,
163 }
164 }
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
169pub struct MemberPermissions {
170 pub can_sign: bool,
171 pub can_propose_operations: bool,
172 pub can_vote: bool,
173}
174
175impl Default for MemberPermissions {
176 fn default() -> Self {
177 Self {
178 can_sign: true,
179 can_propose_operations: true,
180 can_vote: true,
181 }
182 }
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
187pub enum ParticipantStatus {
188 Active,
190
191 PendingJoin,
193
194 PendingRemoval,
196
197 Inactive,
199
200 Suspended { reason: String, until: SystemTime },
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct GroupMetadata {
207 pub name: String,
208 pub description: String,
209 pub purpose: GroupPurpose,
210 pub parent_group: Option<GroupId>,
211 pub custom_data: HashMap<String, String>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
216pub enum GroupPurpose {
217 MultiSig,
219
220 KeyManagement,
222
223 AccessControl,
225
226 Governance,
228
229 Custom(String),
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct GroupAuditEntry {
236 pub timestamp: SystemTime,
237 pub operation: GroupOperation,
238 pub initiator: ParticipantId,
239 pub approvers: Vec<ParticipantId>,
240 pub result: OperationResult,
241 pub metadata: HashMap<String, String>,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub enum GroupOperation {
247 AddParticipant {
249 group_id: GroupId,
250 new_participant: ParticipantInfo,
251 new_threshold: Option<u16>,
252 },
253
254 RemoveParticipant {
256 group_id: GroupId,
257 participant_id: ParticipantId,
258 new_threshold: Option<u16>,
259 },
260
261 UpdateThreshold {
263 group_id: GroupId,
264 new_threshold: u16,
265 },
266
267 RefreshKeys { group_id: GroupId },
269
270 UpdateRole {
272 group_id: GroupId,
273 participant_id: ParticipantId,
274 new_role: ParticipantRole,
275 },
276
277 SuspendParticipant {
279 group_id: GroupId,
280 participant_id: ParticipantId,
281 reason: String,
282 duration: std::time::Duration,
283 },
284
285 CreateSubgroup {
287 parent_group_id: GroupId,
288 subgroup_config: SubgroupConfig,
289 },
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
294pub enum OperationResult {
295 Success,
296 Failed(String),
297 Pending,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
302pub struct SubgroupConfig {
303 pub name: String,
304 pub threshold: u16,
305 pub initial_participants: Vec<ParticipantId>,
306 pub purpose: GroupPurpose,
307}
308
309pub struct ThresholdGroupManager {
311 pub groups: HashMap<GroupId, ThresholdGroup>,
313
314 pub local_shares: HashMap<GroupId, FrostKeyShare>,
316
317 pub pending_operations: HashMap<OperationId, PendingOperation>,
319
320 pub local_identity: QuantumPeerIdentity,
322}
323
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
326pub struct OperationId([u8; 32]);
327
328#[derive(Debug, Clone)]
330pub struct PendingOperation {
331 pub id: OperationId,
332 pub operation: GroupOperation,
333 pub proposed_at: SystemTime,
334 pub proposer: ParticipantId,
335 pub approvals: Vec<ParticipantApproval>,
336 pub rejections: Vec<ParticipantRejection>,
337 pub status: ConsensusStatus,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct ParticipantApproval {
343 pub participant_id: ParticipantId,
344 pub signature: Vec<u8>, pub timestamp: SystemTime,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct ParticipantRejection {
351 pub participant_id: ParticipantId,
352 pub reason: String,
353 pub signature: Vec<u8>, pub timestamp: SystemTime,
355}
356
357#[derive(Debug, Clone, PartialEq)]
359pub enum ConsensusStatus {
360 Pending,
362
363 Approved,
365
366 Rejected,
368
369 TimedOut,
371}
372
373impl ThresholdGroupManager {
374 pub fn new(local_identity: QuantumPeerIdentity) -> Self {
376 Self {
377 groups: HashMap::new(),
378 local_shares: HashMap::new(),
379 pending_operations: HashMap::new(),
380 local_identity,
381 }
382 }
383
384 pub async fn create_group(&mut self, config: GroupConfig) -> Result<ThresholdGroup> {
386 if config.threshold > config.participants.len() as u16 {
388 return Err(ThresholdError::InvalidParameters(
389 "Threshold cannot exceed number of participants".to_string(),
390 ));
391 }
392
393 if config.threshold == 0 {
394 return Err(ThresholdError::InvalidParameters(
395 "Threshold must be at least 1".to_string(),
396 ));
397 }
398
399 let dkg_result = dkg::run_ceremony(config.threshold, config.participants.clone()).await?;
401
402 let group = ThresholdGroup {
404 group_id: GroupId(rand::random()),
405 threshold: config.threshold,
406 participants: config.participants.len() as u16,
407 frost_group_key: dkg_result.group_key,
408 active_participants: config.participants.clone(),
409 pending_participants: Vec::new(),
410 version: 1,
411 metadata: config.metadata.clone(),
412 audit_log: vec![GroupAuditEntry {
413 timestamp: SystemTime::now(),
414 operation: GroupOperation::CreateSubgroup {
415 parent_group_id: GroupId([0; 32]),
416 subgroup_config: SubgroupConfig {
417 name: config.metadata.name.clone(),
418 threshold: config.threshold,
419 initial_participants: config
420 .participants
421 .iter()
422 .map(|p| p.participant_id.clone())
423 .collect(),
424 purpose: config.metadata.purpose.clone(),
425 },
426 },
427 initiator: self.local_identity.peer_id.clone().into(),
428 approvers: vec![],
429 result: OperationResult::Success,
430 metadata: HashMap::new(),
431 }],
432 created_at: SystemTime::now(),
433 last_updated: SystemTime::now(),
434 };
435
436 self.groups.insert(group.group_id.clone(), group.clone());
438 self.local_shares
439 .insert(group.group_id.clone(), dkg_result.local_share);
440
441 Ok(group)
442 }
443
444 pub async fn propose_operation(&mut self, operation: GroupOperation) -> Result<OperationId> {
446 let operation_id = OperationId(rand::random());
447
448 let pending_op = PendingOperation {
449 id: operation_id.clone(),
450 operation,
451 proposed_at: SystemTime::now(),
452 proposer: self.local_identity.peer_id.clone().into(),
453 approvals: vec![],
454 rejections: vec![],
455 status: ConsensusStatus::Pending,
456 };
457
458 self.pending_operations
459 .insert(operation_id.clone(), pending_op);
460
461 Ok(operation_id)
465 }
466}
467
468pub struct GroupConfig {
470 pub threshold: u16,
471 pub participants: Vec<ParticipantInfo>,
472 pub metadata: GroupMetadata,
473}
474
475impl From<PeerId> for ParticipantId {
477 fn from(_peer_id: PeerId) -> Self {
478 ParticipantId(0)
480 }
481}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486
487 #[test]
488 fn test_permission_defaults() {
489 let leader_perms = LeaderPermissions::default();
490 assert!(leader_perms.can_add_participants);
491 assert!(leader_perms.can_remove_participants);
492
493 let member_perms = MemberPermissions::default();
494 assert!(member_perms.can_sign);
495 assert!(member_perms.can_vote);
496 }
497
498 #[test]
499 fn test_participant_roles() {
500 let leader = ParticipantRole::Leader {
501 permissions: LeaderPermissions::default(),
502 };
503
504 let member = ParticipantRole::Member {
505 permissions: MemberPermissions::default(),
506 };
507
508 assert_ne!(leader, member);
509 }
510}