1use crate::coordinator::session::SignerId;
12use serde::{Deserialize, Serialize};
13use std::io::{self, Read, Write};
14use std::net::TcpStream;
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(tag = "type")]
19pub enum ProtocolMessage {
20 Register {
22 signer_id: SignerId,
24 quorum_id: String,
26 },
27 Registered {
29 signer_id: SignerId,
31 },
32 CreateSession {
34 quorum_id: String,
36 scheme: String,
38 message: Vec<u8>,
40 threshold: u32,
42 num_parties: u32,
44 },
45 SessionCreated {
47 session_id: String,
49 },
50 SessionPending {
52 session_id: String,
54 message: Vec<u8>,
56 threshold: u32,
58 },
59 Commitment {
61 session_id: String,
63 signer_id: SignerId,
65 bytes: Vec<u8>,
67 signature: Vec<u8>,
69 },
70 CommitmentsReady {
72 session_id: String,
74 },
75 Share {
77 session_id: String,
79 signer_id: SignerId,
81 bytes: Vec<u8>,
83 signature: Vec<u8>,
85 },
86 Signature {
88 session_id: String,
90 bytes: Vec<u8>,
92 algorithm: String,
94 contributing_signers: Vec<SignerId>,
96 },
97 Ack {
99 session_id: String,
101 },
102 Error {
104 message: String,
106 },
107 GetStatus {
109 session_id: Option<String>,
111 },
112 Status {
114 session_id: String,
116 state: String,
118 },
119 HealthCheck,
121 HealthStatus {
123 alive: bool,
125 ready: bool,
127 session_count: usize,
129 uptime_seconds: u64,
131 },
132}
133
134pub fn send_message(stream: &mut TcpStream, msg: &ProtocolMessage) -> io::Result<()> {
136 let json = serde_json::to_vec(msg)?;
137 let len = json.len() as u32;
138 stream.write_all(&len.to_be_bytes())?;
139 stream.write_all(&json)?;
140 stream.flush()?;
141 Ok(())
142}
143
144pub fn recv_message(stream: &mut TcpStream) -> io::Result<ProtocolMessage> {
146 let mut len_buf = [0u8; 4];
147 stream.read_exact(&mut len_buf)?;
148 let len = u32::from_be_bytes(len_buf) as usize;
149
150 if len > 16 * 1024 * 1024 {
151 return Err(io::Error::new(
152 io::ErrorKind::InvalidData,
153 format!("message too large: {} bytes", len),
154 ));
155 }
156
157 let mut json_buf = vec![0u8; len];
158 stream.read_exact(&mut json_buf)?;
159
160 let msg: ProtocolMessage = serde_json::from_slice(&json_buf)?;
161 Ok(msg)
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn protocol_message_serializes() {
170 let msg = ProtocolMessage::Register {
171 signer_id: "alice".into(),
172 quorum_id: "test".into(),
173 };
174 let json = serde_json::to_vec(&msg).unwrap();
175 assert!(json.len() > 10);
176 let recovered: ProtocolMessage = serde_json::from_slice(&json).unwrap();
177 match recovered {
178 ProtocolMessage::Register {
179 signer_id,
180 quorum_id,
181 } => {
182 assert_eq!(signer_id, "alice");
183 assert_eq!(quorum_id, "test");
184 }
185 _ => panic!("wrong variant"),
186 }
187 }
188
189 #[test]
190 fn all_variants_round_trip() {
191 let messages = vec![
192 ProtocolMessage::Register {
193 signer_id: "a".into(),
194 quorum_id: "q".into(),
195 },
196 ProtocolMessage::Registered {
197 signer_id: "a".into(),
198 },
199 ProtocolMessage::CreateSession {
200 quorum_id: "q".into(),
201 scheme: "FROST-P256".into(),
202 message: vec![1, 2, 3],
203 threshold: 3,
204 num_parties: 5,
205 },
206 ProtocolMessage::SessionCreated {
207 session_id: "s1".into(),
208 },
209 ProtocolMessage::SessionPending {
210 session_id: "s1".into(),
211 message: vec![1, 2, 3],
212 threshold: 3,
213 },
214 ProtocolMessage::Commitment {
215 session_id: "s1".into(),
216 signer_id: "a".into(),
217 bytes: vec![4, 5],
218 signature: vec![6, 7],
219 },
220 ProtocolMessage::Signature {
221 session_id: "s1".into(),
222 bytes: vec![8, 9],
223 algorithm: "FROST-P256".into(),
224 contributing_signers: vec!["a".into(), "b".into()],
225 },
226 ProtocolMessage::Error {
227 message: "test".into(),
228 },
229 ];
230 for msg in &messages {
231 let json = serde_json::to_vec(msg).unwrap();
232 let recovered: ProtocolMessage = serde_json::from_slice(&json).unwrap();
233 let json2 = serde_json::to_vec(&recovered).unwrap();
234 assert_eq!(json, json2, "round-trip must preserve bytes");
235 }
236 }
237}