Skip to main content

archimedes_kernel/movement/
mod.rs

1use 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}