use alloc::vec::Vec;
use crate::daemonic::anchor::{Anchor, AnchorDomainSet, AnchorPermit, StructuralAnchor};
use crate::daemonic::daemonic_hasher::{DaemonicHashable, DaemonicHasher};
use crate::daemonic::glass::{
Glass,
Observation,
Severity,
};
use crate::daemonic::{SemanticAnchor, SymbolicAnchor, TopologyAnchor, TopologySegment};
use alloc::format;
use alloc::string::String;
use core::hash::Hash;
use core::mem;
use crate::{const_daemonic_hash, AXIOM_OFFSET};
use crate::daemonic::daemonic_hasher::random::DefaultDaemonicHasher;
use crate::daemonic::topology::TOPOLOGY_ANCHOR;
#[derive(Clone, Eq, PartialEq)]
pub struct DaemonicID {
#[doc = " Current identity hash — the Merkle root."]
#[doc = " This is what you compare when asking"]
#[doc = " \"are these the same entity?\""]
current: [u8; 32],
#[doc = " How many links in the chain."]
#[doc = " The entity\'s \"age\" in significant state transitions."]
chain_depth: u64,
#[doc = " The construction context that started the chain."]
#[doc = " The birth certificate."]
seed: IdentitySeed,
}
const DAEMONICID_TOPOLOGY: crate::daemonic::TopologySegment = crate::daemonic::TopologySegment {
label: "Daemonic::Glass::Consumer::DaemonicID",
hash: crate::const_daemonic_hash(
"Daemonic::Glass::Consumer::DaemonicID".as_bytes(),
crate::AXIOM_OFFSET,
),
crypto_id: crate::const_daemonic_hash(
"Daemonic::Glass::Consumer::DaemonicID".as_bytes(),
crate::TOPOLOGY_ANCHOR,
),
depth: 3u16,
};
impl crate::daemonic::SymbolicAnchor for DaemonicID {
type Anchor = crate::daemonic::TopologySegment;
fn meaningful_within(&self) -> Self::Anchor {
DAEMONICID_TOPOLOGY.clone()
}
}
impl crate::daemonic::SemanticAnchor for DaemonicID {}
impl crate::daemonic::SpatialAnchor for DaemonicID {
fn anchor_position(&self) -> &crate::daemonic::TopologySegment {
&DAEMONICID_TOPOLOGY
}
fn neighbors(&self) -> crate::daemonic::TopologySegment {
DAEMONICID_TOPOLOGY.clone()
}
}
impl crate::TopologyAnchor for DaemonicID {
fn parent(&self) -> Option<crate::daemonic::TopologySegment> {
let label = DAEMONICID_TOPOLOGY.label;
label
.rsplit_once("::")
.map(|(parent, _)| <TopologySegment as TopologyAnchor>::new_anchor(parent))
}
fn children(&self) -> &[crate::daemonic::TopologySegment] {
&[]
}
fn segments(&self) -> &crate::daemonic::TopologySegment {
&DAEMONICID_TOPOLOGY
}
fn depth(&self) -> usize {
DAEMONICID_TOPOLOGY.depth as usize
}
}
impl DaemonicHashable for [u8; 32] {
fn declare_hashable<GLASS>(&self, state: &mut GLASS) where GLASS: DaemonicHasher<GLASS>, GLASS: Glass<GLASS> {
DaemonicHashable::declare_hashable(&self, state);
}
}
impl DaemonicHashable for DaemonicID {
fn declare_hashable<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self, state: &mut GLASS)
{
DaemonicHashable::declare_hashable(&self.current, state);
DaemonicHashable::declare_hashable(&self.chain_depth, state);
DaemonicHashable::declare_hashable(&self.seed, state);
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct IdentitySeed {
pub parent_id: Option<[u8; 32]>,
pub birth_tick: u64,
pub birth_position: TopologySegment,
pub initial_domains: AnchorDomainSet,
}
impl DaemonicHashable for IdentitySeed {
fn declare_hashable<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self, state: &mut GLASS) {
DaemonicHashable::declare_hashable(&self.parent_id, state);
DaemonicHashable::declare_hashable(&self.birth_tick, state);
DaemonicHashable::declare_hashable(&self.birth_position, state);
DaemonicHashable::declare_hashable(&self.initial_domains, state);
}
}
static IDENTITY_SEED_TOPOLOGY_ANCH0R: TopologySegment = TopologySegment {
label: "Daemonic::Identity",
hash: const_daemonic_hash(
"Daemonic::Identity".as_bytes(),
AXIOM_OFFSET,
),
crypto_id: const_daemonic_hash("Daemonic::Identity".as_bytes(), TOPOLOGY_ANCHOR),
depth: 1u16,
};
impl Glass<IdentitySeed> for IdentitySeed {
type Anchor = TopologySegment;
fn position(&self) -> &TopologySegment {
&IDENTITY_SEED_TOPOLOGY_ANCH0R
}
fn severity(&self) -> Severity {
Severity::Unknown
}
fn payload(&self) -> Option<&IdentitySeed> {
Some(&self)
}
fn into_payload(self) -> Option<IdentitySeed>
where
Self: Sized,
IdentitySeed: Sized
{
Some(self)
}
}
impl <GLASS: DaemonicHasher<GLASS> + Glass<GLASS>> DaemonicHasher<GLASS> for IdentitySeed {
fn finish(&self) -> u64 {
todo!()
}
fn write(&mut self, bytes: &[u8]) {
todo!()
}
}
impl DaemonicHashable for Option<[u8; 32]> {
fn declare_hashable<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self, state: &mut GLASS) {
DaemonicHashable::declare_hashable(&self, state);
}
}
static DEFAULT_DAEMONIC_HASHER_TOPOLOGY_ANCH0R: TopologySegment = TopologySegment {
label: "Daemonic::DaemonicID",
hash: const_daemonic_hash(
"Daemonic::DaemonicID".as_bytes(),
crate::AXIOM_OFFSET,
),
crypto_id: const_daemonic_hash("Daemonic::DaemonicID".as_bytes(), TOPOLOGY_ANCHOR),
depth: 2u16,
};
impl Glass<DaemonicID> for DaemonicID {
type Anchor = TopologySegment;
fn position(&self) -> &TopologySegment {
&DEFAULT_DAEMONIC_HASHER_TOPOLOGY_ANCH0R
}
fn severity(&self) -> Severity {
Severity::Unknown
}
fn payload(&self) -> Option<&DaemonicID> {
Some(&self)
}
fn into_payload(self) -> Option<DaemonicID>
where
Self: Sized,
DaemonicID: Sized
{
Some(self)
}
}
impl DaemonicID {
pub fn new<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(seed: IdentitySeed) -> Self {
let initial_hash = Self::hash_seed::<GLASS>(&seed);
Self {
current: initial_hash,
chain_depth: 1,
seed,
}
}
pub fn root<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(birth_tick: u64, birth_position: TopologySegment) -> Self {
Self::new::<GLASS>(IdentitySeed {
parent_id: None,
birth_tick,
birth_position,
initial_domains: AnchorDomainSet::ALL,
})
}
pub fn child<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(
parent: &DaemonicID,
birth_tick: u64,
birth_position: TopologySegment,
domains: AnchorDomainSet,
) -> Self {
Self::new::<GLASS>(IdentitySeed {
parent_id: Some(parent.current),
birth_tick,
birth_position,
initial_domains: domains,
})
}
pub fn current_hash(&self) -> &[u8; 32] {
&self.current
}
pub fn chain_depth(&self) -> u64 {
self.chain_depth
}
pub fn seed(&self) -> &IdentitySeed {
&self.seed
}
pub fn is_root(&self) -> bool {
self.seed.parent_id.is_none()
}
pub fn is_sibling_of(&self, other: &DaemonicID) -> bool {
self.seed.parent_id == other.seed.parent_id && self.seed.parent_id.is_some()
}
pub fn is_descendant_of(&self, potential_parent: &DaemonicID) -> bool {
self.seed.parent_id.as_ref() == Some(&potential_parent.current)
}
pub fn transition<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&mut self, event: IdentityTransition) {
self.current = Self::chain_link::<GLASS>(&self.current, &event);
self.chain_depth += 1;
}
pub fn broken_sword<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&mut self, position: TopologySegment, tick: u64) {
self.transition::<GLASS>(IdentityTransition {
tick,
severity_before: Severity::Warp, severity_after: Severity::Impossible, position,
anchor_domains: AnchorDomainSet::NONE, cause: TransitionCause::BrokenSword,
});
}
pub fn short_id(&self) -> String {
self.current[..8]
.iter()
.map(|b| format!("{:02x}", b))
.collect()
}
fn hash_seed
<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>
(seed: &IdentitySeed) -> [u8; 32] {
let mut hasher = DefaultDaemonicHasher::new();
DaemonicHashable::declare_hashable(&seed.birth_tick, &mut hasher);
DaemonicHashable::declare_hashable(&seed.birth_position, &mut hasher);
DaemonicHashable::declare_hashable(&seed.initial_domains, &mut hasher);
if let Some(ref parent) = seed.parent_id {
DaemonicHashable::declare_hashable(&parent, &mut hasher);
}
let h = DaemonicHasher::<GLASS>::finish(&hasher);
let mut result = [0u8; 32];
for i in 0..4 {
let mixed = h.wrapping_mul(0x517cc1b727220a95_u64.wrapping_add(i as u64));
result[i * 8..(i + 1) * 8].copy_from_slice(&mixed.to_le_bytes());
}
result
}
fn chain_link<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(previous: &[u8; 32], event: &IdentityTransition) -> [u8; 32] {
let mut hasher = DefaultDaemonicHasher::new();
previous.declare_hashable(&mut hasher);
event.tick.declare_hashable(&mut hasher);
(event.severity_before as u8).declare_hashable(&mut hasher);
(event.severity_after as u8).declare_hashable(&mut hasher);
event.position.declare_hashable(&mut hasher);
event.anchor_domains.declare_hashable(&mut hasher);
let h = DaemonicHasher::<GLASS>::finish(&hasher);
let mut result = [0u8; 32];
for i in 0..4 {
let mixed = h.wrapping_mul(0x9e3779b97f4a7c15_u64.wrapping_add(i as u64));
result[i * 8..(i + 1) * 8].copy_from_slice(&mixed.to_le_bytes());
}
result
}
}
#[derive(Clone, Debug)]
pub struct IdentityTransition {
pub tick: u64,
pub severity_before: Severity,
pub severity_after: Severity,
pub position: TopologySegment,
pub anchor_domains: AnchorDomainSet,
pub cause: TransitionCause,
}
#[derive(Clone, Debug)]
pub enum TransitionCause {
Observation,
Repair { from: Severity, to: Severity },
AnchorShift {
domains_before: AnchorDomainSet,
domains_after: AnchorDomainSet,
},
Migration { from: TopologySegment, to: TopologySegment },
Composition { other_id: [u8; 32] },
AnchorShatter { shattered_anchor_id: u64 },
BrokenSword,
Reconstruction { from_checkpoint: [u8; 32] },
Genesis,
}
pub struct IdentityProvenance {
id: DaemonicID,
transitions: Vec<IdentityTransition>,
recent_window: usize, }
impl IdentityProvenance {
pub fn new(id: DaemonicID) -> Self {
Self {
id,
transitions: Vec::new(),
recent_window: 8, }
}
pub fn record_transition<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&mut self, event: IdentityTransition) {
self.id.transition::<GLASS>(event.clone());
self.transitions.push(event);
}
pub fn recent(&self) -> &[IdentityTransition] {
let start = self.transitions.len().saturating_sub(self.recent_window);
&self.transitions[start..]
}
pub fn transition_count(&self) -> usize {
self.transitions.len()
}
pub fn verify_integrity<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self) -> bool {
let mut computed = DaemonicID::new::<GLASS>(self.id.seed.clone());
for transition in &self.transitions {
computed.transition::<GLASS>(transition.clone());
}
computed.current == self.id.current
}
pub fn divergence_point(&self, other: &IdentityProvenance) -> Option<usize> {
if self.id.seed != other.id.seed {
return Some(0); }
for (i, (a, b)) in self
.transitions
.iter()
.zip(other.transitions.iter())
.enumerate()
{
if a.tick != b.tick
|| a.severity_after != b.severity_after
|| mem::discriminant(&a.cause) != mem::discriminant(&b.cause)
{
return Some(i);
}
}
if self.transitions.len() != other.transitions.len() {
return Some(self.transitions.len().min(other.transitions.len()));
}
None }
pub fn id(&self) -> &DaemonicID {
&self.id
}
}
impl Anchor for DaemonicID {
fn anchor_domains(&self) -> AnchorDomainSet {
AnchorDomainSet::STRUCTURAL.union(AnchorDomainSet::CAUSAL)
}
fn anchor_depth(&self) -> usize {
if self.is_root() { 0 } else { 1 }
}
fn is_recursive_anchor(&self) -> bool {
true
}
fn anchor_reliability(&self) -> f64 {
let depth = self.chain_depth as f64;
todo!("libc breakage, fix")
}
}
impl StructuralAnchor for DaemonicID {
fn contract_description(&self) -> &str {
"DaemonicID: cryptographic identity chain. \
This entity is who it claims to be, verifiable \
through its transition history."
}
fn contract_version(&self) -> u32 {
self.chain_depth as u32
}
fn symmetry_score(&self) -> f64 {
1.0
}
}
impl AnchorPermit for DaemonicID {
fn permits_temporal(&self) -> bool {
false
}
fn permits_spatial(&self) -> bool {
false
}
fn permits_structural(&self) -> bool {
true
} fn permits_perceptual(&self) -> bool {
false
} fn permits_symbolic(&self) -> bool {
true
} fn is_positionally_stable(&self) -> bool {
true
} }
impl SemanticAnchor for IdentitySeed {}
impl Anchor for IdentitySeed {
fn anchor_domains(&self) -> AnchorDomainSet {
AnchorDomainSet::SYMBOLIC.union(AnchorDomainSet::STRUCTURAL)
}
}
impl StructuralAnchor for IdentitySeed {
fn contract_description(&self) -> &str {
"todo!"
}
}
impl SymbolicAnchor for IdentitySeed {
fn meaningful_within(&self) -> Self::Anchor {
TopologySegment::new("Daemonic::IdentitySeed")
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_position() -> TopologySegment {
TopologySegment::new("Daemonic::Test::Identity")
}
#[test]
fn test_root_identity_creation() {
let id = DaemonicID::root(1, test_position());
assert!(id.is_root());
assert_eq!(id.chain_depth(), 1);
}
#[test]
fn test_child_identity_creation() {
let parent = DaemonicID::root(1, test_position());
let child = DaemonicID::child(&parent, 2, test_position(), AnchorDomainSet::TEMPORAL);
assert!(!child.is_root());
assert!(child.is_descendant_of(&parent));
assert_eq!(child.chain_depth(), 1);
}
#[test]
fn test_sibling_detection() {
let parent = DaemonicID::root(1, test_position());
let child_a = DaemonicID::child(&parent, 2, test_position(), AnchorDomainSet::TEMPORAL);
let child_b = DaemonicID::child(&parent, 3, test_position(), AnchorDomainSet::SPATIAL);
assert!(child_a.is_sibling_of(&child_b));
assert!(child_b.is_sibling_of(&child_a));
assert!(!parent.is_sibling_of(&child_a));
}
#[test]
fn test_transition_changes_hash() {
let mut id = DaemonicID::root(1, test_position());
let before = id.current;
id.transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
assert_ne!(id.current, before);
assert_eq!(id.chain_depth(), 2);
}
#[test]
fn test_same_transition_produces_same_hash() {
let mut id_a = DaemonicID::root(1, test_position());
let mut id_b = DaemonicID::root(1, test_position());
let transition = IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
};
id_a.transition(transition.clone());
id_b.transition(transition);
assert_eq!(id_a.current, id_b.current);
}
#[test]
fn test_different_transitions_produce_different_hashes() {
let mut id_a = DaemonicID::root(1, test_position());
let mut id_b = DaemonicID::root(1, test_position());
id_a.transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
id_b.transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Fracture, position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
assert_ne!(id_a.current, id_b.current);
}
#[test]
fn test_broken_sword_seals_chain() {
let mut id = DaemonicID::root(1, test_position());
let depth_before = id.chain_depth();
id.broken_sword(test_position(), 100);
assert_eq!(id.chain_depth(), depth_before + 1);
}
#[test]
fn test_provenance_integrity_verification() {
let id = DaemonicID::root(1, test_position());
let mut provenance = IdentityProvenance::new(id);
provenance.record_transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
provenance.record_transition(IdentityTransition {
tick: 10,
severity_before: Severity::Cracked,
severity_after: Severity::Stable,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Repair {
from: Severity::Cracked,
to: Severity::Stable,
},
});
assert!(provenance.verify_integrity());
assert_eq!(provenance.transition_count(), 2);
}
#[test]
fn test_reconstruction_produces_sister() {
let mut original = DaemonicID::root(1, test_position());
original.transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
let mut reconstructed = DaemonicID::new(original.seed().clone());
reconstructed.transition(IdentityTransition {
tick: 5,
severity_before: Severity::Stable,
severity_after: Severity::Cracked,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Reconstruction {
from_checkpoint: original.current,
},
});
assert_ne!(original.current, reconstructed.current);
assert_eq!(original.seed(), reconstructed.seed());
}
#[test]
fn test_anchor_reliability_grows_with_depth() {
let mut id = DaemonicID::root(1, test_position());
let initial = id.anchor_reliability();
for i in 2..20 {
id.transition(IdentityTransition {
tick: i,
severity_before: Severity::Stable,
severity_after: Severity::Stable,
position: test_position(),
anchor_domains: AnchorDomainSet::ALL,
cause: TransitionCause::Observation,
});
}
let after = id.anchor_reliability();
assert!(
after > initial,
"Reliability should grow with chain depth: {} > {}",
after,
initial
);
assert!(after < 1.0, "Reliability should never reach 1.0: {}", after);
}
}