1use super::*;
4impl Machine<AccessAdmissionLaw, Uninitialized, EmptyData> {
5 pub fn admit_initialize(
7 self,
8 client_caps: serde_json::Value,
9 ) -> Machine<AccessAdmissionLaw, Initializing, InitializingData> {
10 Machine::new(
11 Initializing,
12 InitializingData {
13 client_capabilities: client_caps,
14 },
15 )
16 }
17}
18
19impl Machine<AccessAdmissionLaw, Initializing, InitializingData> {
20 pub fn admit_initialized(
22 self,
23 server_caps: serde_json::Value,
24 ) -> Machine<AccessAdmissionLaw, Initialized, InitializedData> {
25 Machine::new(
26 Initialized,
27 InitializedData {
28 client_capabilities: self.data.client_capabilities,
29 server_capabilities: server_caps,
30 },
31 )
32 }
33}
34
35impl Machine<AccessAdmissionLaw, Initialized, InitializedData> {
36 pub fn admit_shutdown(self) -> Machine<AccessAdmissionLaw, ShutDown, EmptyData> {
38 Machine::new(
39 ShutDown,
40 EmptyData {
41 client_capabilities: Some(self.data.client_capabilities),
42 server_capabilities: Some(self.data.server_capabilities),
43 },
44 )
45 }
46}
47
48impl Machine<AccessAdmissionLaw, ShutDown, EmptyData> {
49 pub fn admit_exit(self) -> Machine<AccessAdmissionLaw, Exited, EmptyData> {
51 Machine::new(
52 Exited,
53 EmptyData {
54 client_capabilities: self.data.client_capabilities,
55 server_capabilities: self.data.server_capabilities,
56 },
57 )
58 }
59}
60
61impl TypestateKernel<AccessAdmissionLaw, Uninitialized, EmptyData>
66 for Machine<AccessAdmissionLaw, Uninitialized, EmptyData>
67{
68 type Input = serde_json::Value;
69 type OutputPhase = Initializing;
70 type OutputData = InitializingData;
71 type Receipt = lsp_max_protocol::Receipt;
72
73 fn validate(&self, _input: &Self::Input) -> Result<(), <AccessAdmissionLaw as Law>::Error> {
74 Ok(())
75 }
76
77 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
78 Initializing
79 }
80
81 fn admit(
82 self,
83 input: Self::Input,
84 ) -> Result<
85 Machine<AccessAdmissionLaw, Self::OutputPhase, Self::OutputData>,
86 <AccessAdmissionLaw as Law>::Error,
87 > {
88 self.validate(&input)?;
89 Ok(self.admit_initialize(input))
90 }
91
92 fn receipt(&self) -> Self::Receipt {
93 let receipt_id = "rcpt-uninitialized".to_string();
94 let hash = sha256(receipt_id.as_bytes());
95 lsp_max_protocol::Receipt {
96 receipt_id,
97 hash,
98 prev_receipt_hash: None,
99 }
100 }
101
102 fn exit(self) -> EmptyData {
103 self.data
104 }
105
106 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
107 validate_and_reconstruct_chain_checked(&history).map_err(chain_err_from_str)?;
108 Ok(Machine::new(Uninitialized, EmptyData::default()))
109 }
110}
111
112impl TypestateKernel<AccessAdmissionLaw, Initializing, InitializingData>
113 for Machine<AccessAdmissionLaw, Initializing, InitializingData>
114{
115 type Input = serde_json::Value;
116 type OutputPhase = Initialized;
117 type OutputData = InitializedData;
118 type Receipt = lsp_max_protocol::Receipt;
119
120 fn validate(&self, _input: &Self::Input) -> Result<(), <AccessAdmissionLaw as Law>::Error> {
121 Ok(())
122 }
123
124 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
125 Initialized
126 }
127
128 fn admit(
129 self,
130 input: Self::Input,
131 ) -> Result<
132 Machine<AccessAdmissionLaw, Self::OutputPhase, Self::OutputData>,
133 <AccessAdmissionLaw as Law>::Error,
134 > {
135 self.validate(&input)?;
136 Ok(self.admit_initialized(input))
137 }
138
139 fn receipt(&self) -> Self::Receipt {
140 let client_caps_json = serde_json::to_string(&self.data.client_capabilities)
141 .unwrap_or_else(|_| "<unserializable>".to_string());
142 let receipt_id = format!("rcpt-uninitialized-to-initializing:{}", client_caps_json);
143 let prev_hash = sha256(b"rcpt-uninitialized");
144 let hash = sha256(format!("{}:{}", prev_hash, receipt_id).as_bytes());
145 lsp_max_protocol::Receipt {
146 receipt_id,
147 hash,
148 prev_receipt_hash: Some(prev_hash),
149 }
150 }
151
152 fn exit(self) -> InitializingData {
153 self.data
154 }
155
156 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
157 if history.len() < 2 {
158 return Err(ChainError::InsufficientHistory {
159 required: 2,
160 got: history.len(),
161 });
162 }
163 let (client_caps, _) =
164 validate_and_reconstruct_chain_checked(&history).map_err(chain_err_from_str)?;
165 Ok(Machine::new(
166 Initializing,
167 InitializingData {
168 client_capabilities: client_caps,
169 },
170 ))
171 }
172}
173
174impl TypestateKernel<AccessAdmissionLaw, Initialized, InitializedData>
175 for Machine<AccessAdmissionLaw, Initialized, InitializedData>
176{
177 type Input = ();
178 type OutputPhase = ShutDown;
179 type OutputData = EmptyData;
180 type Receipt = lsp_max_protocol::Receipt;
181
182 fn validate(&self, _input: &Self::Input) -> Result<(), <AccessAdmissionLaw as Law>::Error> {
183 Ok(())
184 }
185
186 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
187 ShutDown
188 }
189
190 fn admit(
191 self,
192 input: Self::Input,
193 ) -> Result<
194 Machine<AccessAdmissionLaw, Self::OutputPhase, Self::OutputData>,
195 <AccessAdmissionLaw as Law>::Error,
196 > {
197 self.validate(&input)?;
198 Ok(self.admit_shutdown())
199 }
200
201 fn receipt(&self) -> Self::Receipt {
202 let client_caps_json = serde_json::to_string(&self.data.client_capabilities)
203 .unwrap_or_else(|_| "<unserializable>".to_string());
204 let server_caps_json = serde_json::to_string(&self.data.server_capabilities)
205 .unwrap_or_else(|_| "<unserializable>".to_string());
206 let hash_0 = sha256(b"rcpt-uninitialized");
207 let rcpt_1 = format!("rcpt-uninitialized-to-initializing:{}", client_caps_json);
208 let prev_hash = sha256(format!("{}:{}", hash_0, rcpt_1).as_bytes());
209 let receipt_id = format!("rcpt-initializing-to-initialized:{}", server_caps_json);
210 let hash = sha256(format!("{}:{}", prev_hash, receipt_id).as_bytes());
211 lsp_max_protocol::Receipt {
212 receipt_id,
213 hash,
214 prev_receipt_hash: Some(prev_hash),
215 }
216 }
217
218 fn exit(self) -> InitializedData {
219 self.data
220 }
221
222 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
223 if history.len() < 3 {
224 return Err(ChainError::InsufficientHistory {
225 required: 3,
226 got: history.len(),
227 });
228 }
229 let (client_caps, server_caps) =
230 validate_and_reconstruct_chain_checked(&history).map_err(chain_err_from_str)?;
231 Ok(Machine::new(
232 Initialized,
233 InitializedData {
234 client_capabilities: client_caps,
235 server_capabilities: server_caps,
236 },
237 ))
238 }
239}
240
241impl TypestateKernel<AccessAdmissionLaw, ShutDown, EmptyData>
242 for Machine<AccessAdmissionLaw, ShutDown, EmptyData>
243{
244 type Input = ();
245 type OutputPhase = Exited;
246 type OutputData = EmptyData;
247 type Receipt = lsp_max_protocol::Receipt;
248
249 fn validate(&self, _input: &Self::Input) -> Result<(), <AccessAdmissionLaw as Law>::Error> {
250 Ok(())
251 }
252
253 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
254 Exited
255 }
256
257 fn admit(
258 self,
259 input: Self::Input,
260 ) -> Result<
261 Machine<AccessAdmissionLaw, Self::OutputPhase, Self::OutputData>,
262 <AccessAdmissionLaw as Law>::Error,
263 > {
264 self.validate(&input)?;
265 Ok(self.admit_exit())
266 }
267
268 fn receipt(&self) -> Self::Receipt {
269 let client_caps_json = self
270 .data
271 .client_capabilities
272 .as_ref()
273 .map(|c| serde_json::to_string(c).unwrap_or_else(|_| "<unserializable>".to_string()))
274 .unwrap_or_else(|| "null".to_string());
275 let server_caps_json = self
276 .data
277 .server_capabilities
278 .as_ref()
279 .map(|s| serde_json::to_string(s).unwrap_or_else(|_| "<unserializable>".to_string()))
280 .unwrap_or_else(|| "null".to_string());
281 let hash_0 = sha256(b"rcpt-uninitialized");
282 let rcpt_1 = format!("rcpt-uninitialized-to-initializing:{}", client_caps_json);
283 let hash_1 = sha256(format!("{}:{}", hash_0, rcpt_1).as_bytes());
284 let rcpt_2 = format!("rcpt-initializing-to-initialized:{}", server_caps_json);
285 let prev_hash = sha256(format!("{}:{}", hash_1, rcpt_2).as_bytes());
286 let receipt_id = "rcpt-initialized-to-shutdown".to_string();
287 let hash = sha256(format!("{}:{}", prev_hash, receipt_id).as_bytes());
288 lsp_max_protocol::Receipt {
289 receipt_id,
290 hash,
291 prev_receipt_hash: Some(prev_hash),
292 }
293 }
294
295 fn exit(self) -> EmptyData {
296 self.data
297 }
298
299 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
300 if history.len() < 4 {
301 return Err(ChainError::InsufficientHistory {
302 required: 4,
303 got: history.len(),
304 });
305 }
306 let (client_caps, server_caps) =
307 validate_and_reconstruct_chain_checked(&history).map_err(chain_err_from_str)?;
308 Ok(Machine::new(
309 ShutDown,
310 EmptyData {
311 client_capabilities: Some(client_caps),
312 server_capabilities: Some(server_caps),
313 },
314 ))
315 }
316}
317
318impl TypestateKernel<AccessAdmissionLaw, Exited, EmptyData>
319 for Machine<AccessAdmissionLaw, Exited, EmptyData>
320{
321 type Input = ();
322 type OutputPhase = Exited;
323 type OutputData = EmptyData;
324 type Receipt = lsp_max_protocol::Receipt;
325
326 fn validate(&self, _input: &Self::Input) -> Result<(), <AccessAdmissionLaw as Law>::Error> {
327 Err("Already exited")
328 }
329
330 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
331 Exited
332 }
333
334 fn admit(
335 self,
336 _input: Self::Input,
337 ) -> Result<
338 Machine<AccessAdmissionLaw, Self::OutputPhase, Self::OutputData>,
339 <AccessAdmissionLaw as Law>::Error,
340 > {
341 self.validate(&_input)?;
342 Ok(self)
343 }
344
345 fn receipt(&self) -> Self::Receipt {
346 let client_caps_json = self
347 .data
348 .client_capabilities
349 .as_ref()
350 .map(|c| serde_json::to_string(c).unwrap_or_else(|_| "<unserializable>".to_string()))
351 .unwrap_or_else(|| "null".to_string());
352 let server_caps_json = self
353 .data
354 .server_capabilities
355 .as_ref()
356 .map(|s| serde_json::to_string(s).unwrap_or_else(|_| "<unserializable>".to_string()))
357 .unwrap_or_else(|| "null".to_string());
358 let hash_0 = sha256(b"rcpt-uninitialized");
359 let rcpt_1 = format!("rcpt-uninitialized-to-initializing:{}", client_caps_json);
360 let hash_1 = sha256(format!("{}:{}", hash_0, rcpt_1).as_bytes());
361 let rcpt_2 = format!("rcpt-initializing-to-initialized:{}", server_caps_json);
362 let hash_2 = sha256(format!("{}:{}", hash_1, rcpt_2).as_bytes());
363 let rcpt_3 = "rcpt-initialized-to-shutdown".to_string();
364 let prev_hash = sha256(format!("{}:{}", hash_2, rcpt_3).as_bytes());
365 let receipt_id = "rcpt-shutdown-to-exited".to_string();
366 let hash = sha256(format!("{}:{}", prev_hash, receipt_id).as_bytes());
367 lsp_max_protocol::Receipt {
368 receipt_id,
369 hash,
370 prev_receipt_hash: Some(prev_hash),
371 }
372 }
373
374 fn exit(self) -> EmptyData {
375 self.data
376 }
377
378 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
379 if history.len() < 5 {
380 return Err(ChainError::InsufficientHistory {
381 required: 5,
382 got: history.len(),
383 });
384 }
385 let (client_caps, server_caps) =
386 validate_and_reconstruct_chain_checked(&history).map_err(chain_err_from_str)?;
387 Ok(Machine::new(
388 Exited,
389 EmptyData {
390 client_capabilities: Some(client_caps),
391 server_capabilities: Some(server_caps),
392 },
393 ))
394 }
395}