confium_coordinator/
coordinator_factory.rs1use crate::coordinator::coordinator::Coordinator;
4use crate::coordinator::session::SessionRequest;
5use crate::di_container::Container;
6
7pub struct CoordinatorBuilder {
9 container: Container,
10 default_threshold: u32,
11 default_party_count: u32,
12 default_unlock_minutes: u32,
13}
14
15impl CoordinatorBuilder {
16 pub fn new() -> Self {
17 Self {
18 container: Container::new(),
19 default_threshold: 2,
20 default_party_count: 3,
21 default_unlock_minutes: 60,
22 }
23 }
24
25 pub fn with_threshold(mut self, t: u32) -> Self {
27 self.default_threshold = t;
28 self
29 }
30
31 pub fn with_party_count(mut self, n: u32) -> Self {
33 self.default_party_count = n;
34 self
35 }
36
37 pub fn with_unlock_minutes(mut self, m: u32) -> Self {
39 self.default_unlock_minutes = m;
40 self
41 }
42
43 pub fn with_dependency<T, F>(mut self, factory: F) -> Self
45 where
46 T: Send + Sync + 'static,
47 F: Fn() -> T + Send + Sync + 'static,
48 {
49 self.container.register(factory);
50 self
51 }
52
53 pub fn build(&mut self) -> Coordinator {
55 Coordinator::new()
56 }
57
58 pub fn create_default_session(
60 &mut self,
61 coordinator: &mut Coordinator,
62 quorum_id: &str,
63 message: Vec<u8>,
64 ) -> Result<String, String> {
65 let request = SessionRequest {
66 quorum_id: quorum_id.into(),
67 scheme: "CMP20".into(),
68 message,
69 threshold: self.default_threshold,
70 num_parties: self.default_party_count,
71 unlock_window_minutes: self.default_unlock_minutes,
72 requested_by: "factory".into(),
73 };
74 coordinator
75 .create_session(request)
76 .map_err(|e| format!("{e:?}"))
77 }
78
79 pub fn container(&mut self) -> &mut Container {
81 &mut self.container
82 }
83}
84
85impl Default for CoordinatorBuilder {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91pub fn test_coordinator(threshold: u32, party_count: u32) -> Coordinator {
93 let mut builder = CoordinatorBuilder::new()
94 .with_threshold(threshold)
95 .with_party_count(party_count);
96 builder.build()
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn builder_default() {
105 let mut builder = CoordinatorBuilder::new();
106 let coord = builder.build();
107 assert_eq!(coord.session_count(), 0);
108 }
109
110 #[test]
111 fn builder_custom_threshold() {
112 let mut builder = CoordinatorBuilder::new().with_threshold(3);
113 let mut coord = builder.build();
114 let result = builder.create_default_session(&mut coord, "q1", vec![0; 32]);
115 assert!(result.is_ok());
116 }
117
118 #[test]
119 fn builder_custom_party_count() {
120 let mut builder = CoordinatorBuilder::new()
121 .with_threshold(2)
122 .with_party_count(5);
123 let mut coord = builder.build();
124 let result = builder.create_default_session(&mut coord, "q1", vec![0; 32]);
125 assert!(result.is_ok());
126 }
127
128 #[test]
129 fn builder_custom_unlock() {
130 let mut builder = CoordinatorBuilder::new()
131 .with_threshold(2)
132 .with_unlock_minutes(120);
133 let mut coord = builder.build();
134 let result = builder.create_default_session(&mut coord, "q1", vec![0; 32]);
135 assert!(result.is_ok());
136 }
137
138 #[test]
139 fn builder_dependency_injection() {
140 let mut builder = CoordinatorBuilder::new().with_dependency(|| 42i32);
141 let container = builder.container();
142 let result: Option<i32> = container.resolve();
143 assert_eq!(result, Some(42));
144 }
145
146 #[test]
147 fn test_coordinator_helper() {
148 let coord = test_coordinator(2, 3);
149 assert_eq!(coord.session_count(), 0);
150 }
151
152 #[test]
153 fn multiple_sessions_via_builder() {
154 let mut builder = CoordinatorBuilder::new().with_threshold(2);
155 let mut coord = builder.build();
156 let s1 = builder
157 .create_default_session(&mut coord, "q1", vec![0; 32])
158 .unwrap();
159 let s2 = builder
160 .create_default_session(&mut coord, "q2", vec![1; 32])
161 .unwrap();
162 assert_ne!(s1, s2);
163 assert_eq!(coord.session_count(), 2);
164 }
165}