archimedes_kernel/movement/
mod.rs1use serde::{Deserialize, Serialize};
2use sha2::{Digest, Sha256};
3
4use crate::primitives::State;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub struct HashValue(pub [u8; 32]);
8
9impl HashValue {
10 pub fn as_bytes(&self) -> &[u8; 32] {
11 &self.0
12 }
13}
14
15fn write_bytes(hasher: &mut Sha256, bytes: &[u8]) {
16 hasher.update((bytes.len() as u64).to_le_bytes());
17 hasher.update(bytes);
18}
19
20fn write_str(hasher: &mut Sha256, s: &str) {
21 write_bytes(hasher, s.as_bytes());
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub struct Event {
26 pub proposed_field: String,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30pub struct LawCheck {
31 pub result: bool,
32 pub explanation: String,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36pub struct Transition {
37 pub before: State,
38 pub after: State,
39 pub law_check_valid: bool,
40 pub prev_hash: HashValue,
41 pub self_hash: HashValue,
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
45pub struct MovementMemory {
46 pub transitions: Vec<Transition>,
47}
48
49pub fn hash_transition(
50 prev_hash: HashValue,
51 before: &State,
52 after: &State,
53 law_check_valid: bool,
54) -> HashValue {
55 let mut hasher = Sha256::new();
56 hasher.update(prev_hash.0);
57 write_str(&mut hasher, &before.field);
58 write_str(&mut hasher, &after.field);
59 hasher.update([law_check_valid as u8]);
60
61 let result = hasher.finalize();
62 let mut bytes = [0u8; 32];
63 bytes.copy_from_slice(&result);
64 HashValue(bytes)
65}
66
67impl MovementMemory {
68 pub fn current_hash(&self) -> HashValue {
69 self.transitions
70 .last()
71 .map(|t| t.self_hash)
72 .unwrap_or(HashValue([0u8; 32]))
73 }
74
75 pub fn verify_integrity(&self) -> bool {
76 let mut prev_hash = HashValue([0u8; 32]);
77 for t in &self.transitions {
78 let computed = hash_transition(prev_hash, &t.before, &t.after, t.law_check_valid);
79 if computed != t.self_hash || t.prev_hash != prev_hash {
80 return false;
81 }
82 prev_hash = t.self_hash;
83 }
84 true
85 }
86
87 pub fn compose(&self, start: usize, end: usize) -> Option<MovementComposition> {
88 if start > end || end >= self.transitions.len() {
89 return None;
90 }
91
92 let first = &self.transitions[start];
93 let last = &self.transitions[end];
94
95 Some(MovementComposition {
96 start_index: start,
97 end_index: end,
98 start_state: first.before.clone(),
99 end_state: last.after.clone(),
100 hash: last.self_hash,
101 })
102 }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
106pub struct MovementComposition {
107 pub start_index: usize,
108 pub end_index: usize,
109 pub start_state: State,
110 pub end_state: State,
111 pub hash: HashValue,
112}
113
114impl MovementComposition {
115 pub fn verify(&self, memory: &MovementMemory) -> bool {
116 if self.start_index > self.end_index || self.end_index >= memory.transitions.len() {
117 return false;
118 }
119
120 let first = &memory.transitions[self.start_index];
121 let last = &memory.transitions[self.end_index];
122
123 if first.before != self.start_state || last.after != self.end_state {
124 return false;
125 }
126
127 if last.self_hash != self.hash {
128 return false;
129 }
130
131 let mut prev_hash = if self.start_index == 0 {
132 HashValue([0u8; 32])
133 } else {
134 memory.transitions[self.start_index - 1].self_hash
135 };
136
137 for t in &memory.transitions[self.start_index..=self.end_index] {
138 if t.prev_hash != prev_hash {
139 return false;
140 }
141 let computed = hash_transition(prev_hash, &t.before, &t.after, t.law_check_valid);
142 if computed != t.self_hash {
143 return false;
144 }
145 prev_hash = t.self_hash;
146 }
147
148 true
149 }
150}