lsp_max/runtime/control_plane/kernel/
admitted_superseded.rs1use crate::runtime::control_plane::admission::{
2 AdmittedData, GraphAdmissionError, GraphAdmissionLaw, SupersededData, ADMITTED, SUPERSEDED,
3};
4use crate::runtime::control_plane::receipts::{Blake3Hash, CryptographicReceipt};
5use crate::runtime::{ChainError, Machine, TypestateKernel};
6use ed25519_dalek::Signer;
7
8impl TypestateKernel<GraphAdmissionLaw, ADMITTED, AdmittedData>
12 for Machine<GraphAdmissionLaw, ADMITTED, AdmittedData>
13{
14 type Input = oxigraph::model::GraphName;
15 type OutputPhase = SUPERSEDED;
16 type OutputData = SupersededData;
17 type Receipt = CryptographicReceipt;
18
19 fn validate(&self, _input: &Self::Input) -> Result<(), GraphAdmissionError> {
20 Ok(())
21 }
22
23 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
24 SUPERSEDED
25 }
26
27 fn admit(
28 self,
29 input: Self::Input,
30 ) -> Result<Machine<GraphAdmissionLaw, Self::OutputPhase, Self::OutputData>, GraphAdmissionError>
31 {
32 self.validate(&input)?;
33 Ok(self.admit_supersede(input))
34 }
35
36 fn receipt(&self) -> Self::Receipt {
37 self.data.receipt.clone()
38 }
39
40 fn exit(self) -> AdmittedData {
41 self.data
42 }
43
44 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
45 if history.len() < 3 {
46 return Err(ChainError::InsufficientHistory {
47 required: 3,
48 got: history.len(),
49 });
50 }
51 let signing_key = ed25519_dalek::SigningKey::from_bytes(&[0u8; 32]);
52 let verifying_key = signing_key.verifying_key();
53 crate::runtime::control_plane::receipts::verify_receipt_chain(
54 &history,
55 &verifying_key,
56 &history[0].prev_hash,
57 )
58 .map_err(|e| ChainError::HashMismatch {
59 index: 2,
60 expected: "Valid signature".to_string(),
61 got: e.to_string(),
62 })?;
63
64 Ok(Machine::new(
65 ADMITTED,
66 AdmittedData {
67 graph_name: oxigraph::model::GraphName::DefaultGraph,
68 quad_count: 0,
69 receipt: history[2].clone(),
70 },
71 ))
72 }
73}
74
75impl TypestateKernel<GraphAdmissionLaw, SUPERSEDED, SupersededData>
79 for Machine<GraphAdmissionLaw, SUPERSEDED, SupersededData>
80{
81 type Input = ();
82 type OutputPhase = SUPERSEDED;
83 type OutputData = SupersededData;
84 type Receipt = CryptographicReceipt;
85
86 fn validate(&self, _input: &Self::Input) -> Result<(), GraphAdmissionError> {
87 Err(GraphAdmissionError::ParsingFailed(
88 "Already superseded".to_string(),
89 ))
90 }
91
92 fn select(&self, _input: &Self::Input) -> Self::OutputPhase {
93 SUPERSEDED
94 }
95
96 fn admit(
97 self,
98 input: Self::Input,
99 ) -> Result<Machine<GraphAdmissionLaw, Self::OutputPhase, Self::OutputData>, GraphAdmissionError>
100 {
101 self.validate(&input)?;
102 Ok(self)
103 }
104
105 fn receipt(&self) -> Self::Receipt {
106 let mut receipt = CryptographicReceipt {
107 prev_hash: Blake3Hash([0u8; 32]),
108 discipline_id: uuid::Uuid::nil(),
109 law_id: uuid::Uuid::nil(),
110 consequence_hash: Blake3Hash([0u8; 32]),
111 sequence: 3,
112 signature: [0u8; 64],
113 };
114 let payload_hash = receipt.compute_payload_hash();
115 let signing_key = ed25519_dalek::SigningKey::from_bytes(&[0u8; 32]);
116 receipt.signature = signing_key.sign(&payload_hash.0).to_bytes();
117 receipt
118 }
119
120 fn exit(self) -> SupersededData {
121 self.data
122 }
123
124 fn replay(history: Vec<Self::Receipt>) -> Result<Self, ChainError> {
125 if history.len() < 4 {
126 return Err(ChainError::InsufficientHistory {
127 required: 4,
128 got: history.len(),
129 });
130 }
131 let signing_key = ed25519_dalek::SigningKey::from_bytes(&[0u8; 32]);
132 let verifying_key = signing_key.verifying_key();
133 crate::runtime::control_plane::receipts::verify_receipt_chain(
134 &history,
135 &verifying_key,
136 &history[0].prev_hash,
137 )
138 .map_err(|e| ChainError::HashMismatch {
139 index: 3,
140 expected: "Valid signature".to_string(),
141 got: e.to_string(),
142 })?;
143
144 Ok(Machine::new(
145 SUPERSEDED,
146 SupersededData {
147 graph_name: oxigraph::model::GraphName::DefaultGraph,
148 superseded_by: oxigraph::model::GraphName::DefaultGraph,
149 },
150 ))
151 }
152}