confium_coordinator/coordinator/
net.rs1use crate::coordinator::session::SignerId;
12use serde::{Deserialize, Serialize};
13use std::io;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(tag = "type")]
18pub enum ProtocolMessage {
19 Register {
21 signer_id: SignerId,
23 quorum_id: String,
25 },
26 Registered {
28 signer_id: SignerId,
30 },
31 CreateSession {
33 quorum_id: String,
35 scheme: String,
37 message: Vec<u8>,
39 threshold: u32,
41 num_parties: u32,
43 },
44 SessionCreated {
46 session_id: String,
48 },
49 SessionPending {
51 session_id: String,
53 message: Vec<u8>,
55 threshold: u32,
57 },
58 Commitment {
60 session_id: String,
62 signer_id: SignerId,
64 bytes: Vec<u8>,
66 signature: Vec<u8>,
68 },
69 CommitmentsReady {
71 session_id: String,
73 },
74 Share {
76 session_id: String,
78 signer_id: SignerId,
80 bytes: Vec<u8>,
82 signature: Vec<u8>,
84 },
85 Signature {
87 session_id: String,
89 bytes: Vec<u8>,
91 algorithm: String,
93 contributing_signers: Vec<SignerId>,
95 },
96 Ack {
98 session_id: String,
100 },
101 Error {
103 message: String,
105 },
106 GetStatus {
108 session_id: Option<String>,
110 },
111 Status {
113 session_id: String,
115 state: String,
117 },
118 HealthCheck,
120 HealthStatus {
122 alive: bool,
124 ready: bool,
126 session_count: usize,
128 uptime_seconds: u64,
130 },
131 MetricsQuery,
133 MetricsResponse {
135 text: String,
137 },
138}
139
140pub fn send_message<S: std::io::Write + ?Sized>(
142 stream: &mut S,
143 msg: &ProtocolMessage,
144) -> io::Result<()> {
145 let json = serde_json::to_vec(msg)?;
146 let len = json.len() as u32;
147 stream.write_all(&len.to_be_bytes())?;
148 stream.write_all(&json)?;
149 stream.flush()?;
150 Ok(())
151}
152
153pub fn recv_message<S: std::io::Read + ?Sized>(stream: &mut S) -> io::Result<ProtocolMessage> {
155 let mut len_buf = [0u8; 4];
156 stream.read_exact(&mut len_buf)?;
157 let len = u32::from_be_bytes(len_buf) as usize;
158
159 if len > 16 * 1024 * 1024 {
160 return Err(io::Error::new(
161 io::ErrorKind::InvalidData,
162 format!("message too large: {} bytes", len),
163 ));
164 }
165
166 let mut json_buf = vec![0u8; len];
167 stream.read_exact(&mut json_buf)?;
168
169 let msg: ProtocolMessage = serde_json::from_slice(&json_buf)?;
170 Ok(msg)
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn protocol_message_serializes() {
179 let msg = ProtocolMessage::Register {
180 signer_id: "alice".into(),
181 quorum_id: "test".into(),
182 };
183 let json = serde_json::to_vec(&msg).unwrap();
184 assert!(json.len() > 10);
185 let recovered: ProtocolMessage = serde_json::from_slice(&json).unwrap();
186 match recovered {
187 ProtocolMessage::Register {
188 signer_id,
189 quorum_id,
190 } => {
191 assert_eq!(signer_id, "alice");
192 assert_eq!(quorum_id, "test");
193 }
194 _ => panic!("wrong variant"),
195 }
196 }
197
198 #[test]
199 fn all_variants_round_trip() {
200 let messages = vec![
201 ProtocolMessage::Register {
202 signer_id: "a".into(),
203 quorum_id: "q".into(),
204 },
205 ProtocolMessage::Registered {
206 signer_id: "a".into(),
207 },
208 ProtocolMessage::CreateSession {
209 quorum_id: "q".into(),
210 scheme: "FROST-P256".into(),
211 message: vec![1, 2, 3],
212 threshold: 3,
213 num_parties: 5,
214 },
215 ProtocolMessage::SessionCreated {
216 session_id: "s1".into(),
217 },
218 ProtocolMessage::SessionPending {
219 session_id: "s1".into(),
220 message: vec![1, 2, 3],
221 threshold: 3,
222 },
223 ProtocolMessage::Commitment {
224 session_id: "s1".into(),
225 signer_id: "a".into(),
226 bytes: vec![4, 5],
227 signature: vec![6, 7],
228 },
229 ProtocolMessage::Signature {
230 session_id: "s1".into(),
231 bytes: vec![8, 9],
232 algorithm: "FROST-P256".into(),
233 contributing_signers: vec!["a".into(), "b".into()],
234 },
235 ProtocolMessage::Error {
236 message: "test".into(),
237 },
238 ];
239 for msg in &messages {
240 let json = serde_json::to_vec(msg).unwrap();
241 let recovered: ProtocolMessage = serde_json::from_slice(&json).unwrap();
242 let json2 = serde_json::to_vec(&recovered).unwrap();
243 assert_eq!(json, json2, "round-trip must preserve bytes");
244 }
245 }
246}