archimedes-kernel 2.0.0

Minimal lawful movement kernel for disciplined digital reality construction
Documentation
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};

use crate::primitives::State;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct HashValue(pub [u8; 32]);

impl HashValue {
    pub fn as_bytes(&self) -> &[u8; 32] {
        &self.0
    }
}

fn write_bytes(hasher: &mut Sha256, bytes: &[u8]) {
    hasher.update((bytes.len() as u64).to_le_bytes());
    hasher.update(bytes);
}

fn write_str(hasher: &mut Sha256, s: &str) {
    write_bytes(hasher, s.as_bytes());
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Event {
    pub proposed_field: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LawCheck {
    pub result: bool,
    pub explanation: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Transition {
    pub before: State,
    pub after: State,
    pub law_check_valid: bool,
    pub prev_hash: HashValue,
    pub self_hash: HashValue,
}

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct MovementMemory {
    pub transitions: Vec<Transition>,
}

pub fn hash_transition(
    prev_hash: HashValue,
    before: &State,
    after: &State,
    law_check_valid: bool,
) -> HashValue {
    let mut hasher = Sha256::new();
    hasher.update(prev_hash.0);
    write_str(&mut hasher, &before.field);
    write_str(&mut hasher, &after.field);
    hasher.update([law_check_valid as u8]);

    let result = hasher.finalize();
    let mut bytes = [0u8; 32];
    bytes.copy_from_slice(&result);
    HashValue(bytes)
}

impl MovementMemory {
    pub fn current_hash(&self) -> HashValue {
        self.transitions
            .last()
            .map(|t| t.self_hash)
            .unwrap_or(HashValue([0u8; 32]))
    }

    pub fn verify_integrity(&self) -> bool {
        let mut prev_hash = HashValue([0u8; 32]);
        for t in &self.transitions {
            let computed = hash_transition(prev_hash, &t.before, &t.after, t.law_check_valid);
            if computed != t.self_hash || t.prev_hash != prev_hash {
                return false;
            }
            prev_hash = t.self_hash;
        }
        true
    }

    pub fn compose(&self, start: usize, end: usize) -> Option<MovementComposition> {
        if start > end || end >= self.transitions.len() {
            return None;
        }

        let first = &self.transitions[start];
        let last = &self.transitions[end];

        Some(MovementComposition {
            start_index: start,
            end_index: end,
            start_state: first.before.clone(),
            end_state: last.after.clone(),
            hash: last.self_hash,
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MovementComposition {
    pub start_index: usize,
    pub end_index: usize,
    pub start_state: State,
    pub end_state: State,
    pub hash: HashValue,
}

impl MovementComposition {
    pub fn verify(&self, memory: &MovementMemory) -> bool {
        if self.start_index > self.end_index || self.end_index >= memory.transitions.len() {
            return false;
        }

        let first = &memory.transitions[self.start_index];
        let last = &memory.transitions[self.end_index];

        if first.before != self.start_state || last.after != self.end_state {
            return false;
        }

        if last.self_hash != self.hash {
            return false;
        }

        let mut prev_hash = if self.start_index == 0 {
            HashValue([0u8; 32])
        } else {
            memory.transitions[self.start_index - 1].self_hash
        };

        for t in &memory.transitions[self.start_index..=self.end_index] {
            if t.prev_hash != prev_hash {
                return false;
            }
            let computed = hash_transition(prev_hash, &t.before, &t.after, t.law_check_valid);
            if computed != t.self_hash {
                return false;
            }
            prev_hash = t.self_hash;
        }

        true
    }
}