use hemera::hash as hemera_hash;
use crate::types::Particle;
pub const STAT_RELATIONS: usize = 11;
pub mod rel {
pub const PARTICLES: usize = 0;
pub const AXONS_OUT: usize = 1;
pub const AXONS_IN: usize = 2;
pub const NEURONS: usize = 3;
pub const LOCATIONS: usize = 4;
pub const COINS: usize = 5;
pub const CARDS: usize = 6;
pub const FILES: usize = 7;
pub const TIME: usize = 8;
pub const SIGNALS: usize = 9;
pub const BALANCES: usize = 10;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GraphStats {
pub node_count: u64,
pub relation_sizes: [u64; STAT_RELATIONS],
pub max_degree: u64,
pub diameter_bound: u64,
}
impl GraphStats {
pub fn serialize(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(8 * (1 + STAT_RELATIONS + 2));
buf.extend_from_slice(&self.node_count.to_le_bytes());
for s in &self.relation_sizes {
buf.extend_from_slice(&s.to_le_bytes());
}
buf.extend_from_slice(&self.max_degree.to_le_bytes());
buf.extend_from_slice(&self.diameter_bound.to_le_bytes());
buf
}
pub fn commit(&self) -> Particle {
let h = hemera_hash(&self.serialize());
let b = h.as_bytes();
let mut out = [0u8; 32];
let len = b.len().min(32);
out[..len].copy_from_slice(&b[..len]);
out
}
}
#[cfg(test)]
mod tests {
use super::*;
fn stats(node_count: u64, diameter_bound: u64) -> GraphStats {
GraphStats {
node_count,
relation_sizes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
max_degree: 4,
diameter_bound,
}
}
#[test]
fn serialize_length_is_fixed() {
assert_eq!(stats(100, 99).serialize().len(), 14 * 8);
}
#[test]
fn commit_is_deterministic() {
assert_eq!(stats(100, 99).commit(), stats(100, 99).commit());
}
#[test]
fn different_node_count_changes_commitment() {
assert_ne!(stats(100, 99).commit(), stats(101, 99).commit());
}
#[test]
fn different_diameter_changes_commitment() {
assert_ne!(stats(100, 99).commit(), stats(100, 50).commit());
}
#[test]
fn relation_index_constants_cover_all_slots() {
assert_eq!(rel::BALANCES, STAT_RELATIONS - 1);
}
}