use ruvector_verified::{
ProofEnvironment, ProofAttestation, VerifiedOp,
prove_dim_eq,
proof_store::create_attestation,
gated::{route_proof, ProofKind, TierDecision, ProofTier},
pipeline::compose_chain,
};
use crate::error::Result;
pub struct ProofGate<T> {
value: T,
attestation_chain: AttestationChain,
env: ProofEnvironment,
}
impl<T> ProofGate<T> {
pub fn new(value: T) -> Self {
Self {
value,
attestation_chain: AttestationChain::new(),
env: ProofEnvironment::new(),
}
}
pub fn read(&self) -> &T {
&self.value
}
pub fn mutate_with_dim_proof(
&mut self,
expected_dim: u32,
actual_dim: u32,
f: impl FnOnce(&mut T),
) -> Result<ProofAttestation> {
let proof_id = prove_dim_eq(&mut self.env, expected_dim, actual_dim)?;
f(&mut self.value);
let attestation = create_attestation(&self.env, proof_id);
self.attestation_chain.append(attestation.clone());
Ok(attestation)
}
pub fn mutate_with_routed_proof(
&mut self,
proof_kind: ProofKind,
expected_id: u32,
actual_id: u32,
f: impl FnOnce(&mut T),
) -> Result<(TierDecision, ProofAttestation)> {
let decision = route_proof(proof_kind, &self.env);
let proof_id = ruvector_verified::gated::verify_tiered(
&mut self.env,
expected_id,
actual_id,
decision.tier,
)?;
f(&mut self.value);
let attestation = create_attestation(&self.env, proof_id);
self.attestation_chain.append(attestation.clone());
Ok((decision, attestation))
}
pub fn mutate_with_pipeline_proof(
&mut self,
stages: &[(String, u32, u32)],
f: impl FnOnce(&mut T),
) -> Result<ProofAttestation> {
let (_input_type, _output_type, proof_id) =
compose_chain(stages, &mut self.env)?;
f(&mut self.value);
let attestation = create_attestation(&self.env, proof_id);
self.attestation_chain.append(attestation.clone());
Ok(attestation)
}
pub fn attestation_chain(&self) -> &AttestationChain {
&self.attestation_chain
}
pub fn proof_stats(&self) -> &ruvector_verified::ProofStats {
self.env.stats()
}
pub fn reset_env(&mut self) {
self.env.reset();
}
}
pub trait ProofGatedMutation {
type ProofObligation;
fn apply_gated(
&mut self,
env: &mut ProofEnvironment,
obligation: &Self::ProofObligation,
) -> Result<VerifiedOp<()>>;
}
#[derive(Debug, Clone)]
pub struct AttestationChain {
entries: Vec<AttestationEntry>,
}
#[derive(Debug, Clone)]
pub struct AttestationEntry {
pub sequence: u64,
pub attestation: ProofAttestation,
}
impl AttestationChain {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn append(&mut self, attestation: ProofAttestation) {
let sequence = self.entries.len() as u64;
self.entries.push(AttestationEntry {
sequence,
attestation,
});
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn latest(&self) -> Option<&AttestationEntry> {
self.entries.last()
}
pub fn iter(&self) -> impl Iterator<Item = &AttestationEntry> {
self.entries.iter()
}
pub fn verify_integrity(&self) -> bool {
self.entries
.iter()
.enumerate()
.all(|(i, entry)| entry.sequence == i as u64)
}
pub fn chain_hash(&self) -> u64 {
let mut h: u64 = 0xcbf29ce484222325;
for entry in &self.entries {
h ^= entry.sequence;
h = h.wrapping_mul(0x100000001b3);
h ^= entry.attestation.content_hash();
h = h.wrapping_mul(0x100000001b3);
}
h
}
}
impl Default for AttestationChain {
fn default() -> Self {
Self::new()
}
}
const FNV_OFFSET_BASIS: u64 = 0xcbf29ce484222325;
const FNV_PRIME: u64 = 0x100000001b3;
#[derive(Debug, Clone)]
pub struct MutationLedger {
attestations: Vec<ProofAttestation>,
chain_hash: u64,
epoch: u64,
compaction_threshold: usize,
}
impl MutationLedger {
pub fn new(compaction_threshold: usize) -> Self {
Self {
attestations: Vec::new(),
chain_hash: FNV_OFFSET_BASIS,
epoch: 0,
compaction_threshold,
}
}
pub fn append(&mut self, att: ProofAttestation) -> u64 {
let position = self.attestations.len() as u64;
self.chain_hash ^= att.content_hash();
self.chain_hash = self.chain_hash.wrapping_mul(FNV_PRIME);
self.attestations.push(att);
position
}
pub fn compact(&mut self) -> ProofAttestation {
let total_steps: u32 = self.attestations
.iter()
.map(|a| a.reduction_steps)
.sum();
let total_cache: u64 = self.attestations
.iter()
.map(|a| a.cache_hit_rate_bps as u64)
.sum();
let avg_cache = if self.attestations.is_empty() {
0u16
} else {
(total_cache / self.attestations.len() as u64) as u16
};
let mut proof_hash = [0u8; 32];
proof_hash[0..8].copy_from_slice(&self.chain_hash.to_le_bytes());
proof_hash[8..16].copy_from_slice(
&(self.attestations.len() as u64).to_le_bytes(),
);
let env_hash = self.attestations
.last()
.map(|a| a.environment_hash)
.unwrap_or([0u8; 32]);
let seal = ProofAttestation::new(proof_hash, env_hash, total_steps, avg_cache);
self.attestations.clear();
self.attestations.push(seal.clone());
self.chain_hash = FNV_OFFSET_BASIS;
self.chain_hash ^= seal.content_hash();
self.chain_hash = self.chain_hash.wrapping_mul(FNV_PRIME);
seal
}
pub fn verify_integrity(&self) -> bool {
let mut h: u64 = FNV_OFFSET_BASIS;
for att in &self.attestations {
h ^= att.content_hash();
h = h.wrapping_mul(FNV_PRIME);
}
h == self.chain_hash
}
pub fn chain_hash(&self) -> u64 {
self.chain_hash
}
pub fn epoch(&self) -> u64 {
self.epoch
}
pub fn set_epoch(&mut self, epoch: u64) {
self.epoch = epoch;
}
pub fn len(&self) -> usize {
self.attestations.len()
}
pub fn is_empty(&self) -> bool {
self.attestations.is_empty()
}
pub fn needs_compaction(&self) -> bool {
self.attestations.len() >= self.compaction_threshold
}
pub fn compaction_threshold(&self) -> usize {
self.compaction_threshold
}
pub fn iter(&self) -> impl Iterator<Item = &ProofAttestation> {
self.attestations.iter()
}
}
#[derive(Debug, Clone)]
pub struct ProofScope {
partition_id: u32,
boundary_nodes: Vec<u64>,
ledger: MutationLedger,
coherence: Option<f64>,
}
impl ProofScope {
pub fn new(
partition_id: u32,
boundary_nodes: Vec<u64>,
compaction_threshold: usize,
) -> Self {
Self {
partition_id,
boundary_nodes,
ledger: MutationLedger::new(compaction_threshold),
coherence: None,
}
}
pub fn partition_id(&self) -> u32 {
self.partition_id
}
pub fn boundary_nodes(&self) -> &[u64] {
&self.boundary_nodes
}
pub fn ledger(&self) -> &MutationLedger {
&self.ledger
}
pub fn ledger_mut(&mut self) -> &mut MutationLedger {
&mut self.ledger
}
pub fn coherence(&self) -> Option<f64> {
self.coherence
}
pub fn set_coherence(&mut self, coherence: f64) {
self.coherence = Some(coherence);
}
pub fn transition(
&mut self,
new_partition_id: u32,
new_boundary_nodes: Vec<u64>,
min_cut_value: f64,
) -> ScopeTransitionAttestation {
let seal = self.ledger.compact();
let old_partition_id = self.partition_id;
let old_coherence = self.coherence;
self.partition_id = new_partition_id;
self.boundary_nodes = new_boundary_nodes;
self.coherence = None;
let threshold = self.ledger.compaction_threshold();
self.ledger = MutationLedger::new(threshold);
ScopeTransitionAttestation {
old_partition_id,
new_partition_id,
min_cut_value,
old_coherence,
seal,
}
}
}
#[derive(Debug, Clone)]
pub struct ScopeTransitionAttestation {
pub old_partition_id: u32,
pub new_partition_id: u32,
pub min_cut_value: f64,
pub old_coherence: Option<f64>,
pub seal: ProofAttestation,
}
#[derive(Debug, Clone)]
pub struct SupersessionProof {
pub superseded_position: u64,
pub replacement: ProofAttestation,
pub soundness_proof_id: u32,
}
impl SupersessionProof {
pub fn new(
superseded_position: u64,
replacement: ProofAttestation,
soundness_proof_id: u32,
) -> Self {
Self {
superseded_position,
replacement,
soundness_proof_id,
}
}
}
#[derive(Debug, Clone)]
pub struct ProofEnvironmentConfig {
pub max_standard_fuel: u32,
pub max_deep_steps: u32,
pub builtin_symbols: u32,
}
impl Default for ProofEnvironmentConfig {
fn default() -> Self {
Self {
max_standard_fuel: 500,
max_deep_steps: 10_000,
builtin_symbols: 64,
}
}
}
#[derive(Debug, Clone)]
pub struct EpochBoundary {
pub from_epoch: u64,
pub to_epoch: u64,
pub seal: ProofAttestation,
pub new_config: ProofEnvironmentConfig,
}
impl EpochBoundary {
pub fn seal(
ledger: &mut MutationLedger,
new_config: ProofEnvironmentConfig,
) -> Self {
let from_epoch = ledger.epoch();
let to_epoch = from_epoch + 1;
let seal_att = ledger.compact();
ledger.set_epoch(to_epoch);
Self {
from_epoch,
to_epoch,
seal: seal_att,
new_config,
}
}
}
#[derive(Debug, Clone)]
pub enum ProofRequirement {
DimensionMatch { expected: u32 },
TypeMatch { schema_id: u64 },
InvariantPreserved { invariant_id: u32 },
CoherenceBound { min_coherence: f64 },
Composite(Vec<ProofRequirement>),
}
impl ProofRequirement {
pub fn to_proof_kind(&self) -> ProofKind {
match self {
ProofRequirement::DimensionMatch { expected } => ProofKind::DimensionEquality { expected: *expected, actual: *expected },
ProofRequirement::TypeMatch { .. } => ProofKind::TypeApplication { depth: 1 },
ProofRequirement::InvariantPreserved { .. } => ProofKind::Custom { estimated_complexity: 100 },
ProofRequirement::CoherenceBound { .. } => ProofKind::Custom { estimated_complexity: 100 },
ProofRequirement::Composite(subs) => {
if subs.iter().any(|r| matches!(
r,
ProofRequirement::InvariantPreserved { .. }
| ProofRequirement::CoherenceBound { .. }
)) {
ProofKind::Custom { estimated_complexity: 100 }
} else if subs.iter().any(|r| {
matches!(r, ProofRequirement::TypeMatch { .. })
}) {
ProofKind::TypeApplication { depth: 1 }
} else {
ProofKind::DimensionEquality { expected: 0, actual: 0 }
}
}
}
}
pub fn leaf_count(&self) -> usize {
match self {
ProofRequirement::Composite(subs) => {
subs.iter().map(|s| s.leaf_count()).sum()
}
_ => 1,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComplexityClass {
Constant,
Logarithmic,
Linear,
Linearithmic,
Quadratic,
}
#[derive(Debug, Clone)]
pub struct ComplexityBound {
pub ops_upper_bound: u64,
pub memory_upper_bound: u64,
pub complexity_class: ComplexityClass,
}
impl ComplexityBound {
pub fn new(
ops_upper_bound: u64,
memory_upper_bound: u64,
complexity_class: ComplexityClass,
) -> Self {
Self {
ops_upper_bound,
memory_upper_bound,
complexity_class,
}
}
pub fn fits_reflex(&self) -> bool {
self.complexity_class == ComplexityClass::Constant
&& self.ops_upper_bound <= 10
}
pub fn fits_standard(&self) -> bool {
self.ops_upper_bound <= 500
}
}
#[derive(Debug, Clone)]
pub enum ProofClass {
Formal,
Statistical {
iterations: u64,
tolerance: f64,
rng_seed: u64,
},
}
impl ProofClass {
pub fn is_formal(&self) -> bool {
matches!(self, ProofClass::Formal)
}
pub fn is_statistical(&self) -> bool {
matches!(self, ProofClass::Statistical { .. })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_proof_gate_create_and_read() {
let gate = ProofGate::new(42u32);
assert_eq!(*gate.read(), 42);
assert!(gate.attestation_chain().is_empty());
}
#[test]
fn test_proof_gate_dim_mutation() {
let mut gate = ProofGate::new(vec![0.0f32; 128]);
let att = gate.mutate_with_dim_proof(128, 128, |v| {
v[0] = 1.0;
});
assert!(att.is_ok());
assert_eq!(gate.read()[0], 1.0);
assert_eq!(gate.attestation_chain().len(), 1);
}
#[test]
fn test_proof_gate_dim_mutation_fails() {
let mut gate = ProofGate::new(vec![0.0f32; 64]);
let att = gate.mutate_with_dim_proof(128, 64, |v| {
v[0] = 1.0;
});
assert!(att.is_err());
assert_eq!(gate.read()[0], 0.0);
assert!(gate.attestation_chain().is_empty());
}
#[test]
fn test_proof_gate_routed_mutation() {
let mut gate = ProofGate::new(100i32);
let result = gate.mutate_with_routed_proof(
ProofKind::Reflexivity,
5,
5,
|v| *v += 1,
);
assert!(result.is_ok());
let (decision, _att) = result.unwrap();
assert_eq!(decision.tier, ProofTier::Reflex);
assert_eq!(*gate.read(), 101);
}
#[test]
fn test_attestation_chain_integrity() {
let mut chain = AttestationChain::new();
let env = ProofEnvironment::new();
for i in 0..5 {
let att = create_attestation(&env, i);
chain.append(att);
}
assert_eq!(chain.len(), 5);
assert!(chain.verify_integrity());
}
#[test]
fn test_attestation_chain_hash_deterministic() {
let mut chain1 = AttestationChain::new();
let mut chain2 = AttestationChain::new();
let env = ProofEnvironment::new();
let att = create_attestation(&env, 0);
chain1.append(att.clone());
chain2.append(att);
assert_ne!(chain1.chain_hash(), 0);
assert_ne!(chain2.chain_hash(), 0);
}
#[test]
fn test_mutation_ledger_append() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(100);
assert!(ledger.is_empty());
assert_eq!(ledger.len(), 0);
let att0 = create_attestation(&env, 0);
let pos0 = ledger.append(att0);
assert_eq!(pos0, 0);
assert_eq!(ledger.len(), 1);
let att1 = create_attestation(&env, 1);
let pos1 = ledger.append(att1);
assert_eq!(pos1, 1);
assert_eq!(ledger.len(), 2);
assert!(!ledger.is_empty());
}
#[test]
fn test_mutation_ledger_integrity_after_appends() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(100);
for i in 0..10 {
let att = create_attestation(&env, i);
ledger.append(att);
}
assert!(ledger.verify_integrity());
}
#[test]
fn test_mutation_ledger_compact() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(5);
for i in 0..5 {
let att = create_attestation(&env, i);
ledger.append(att);
}
assert_eq!(ledger.len(), 5);
assert!(ledger.needs_compaction());
let seal = ledger.compact();
assert_eq!(ledger.len(), 1);
assert!(!ledger.needs_compaction());
let encoded_hash =
u64::from_le_bytes(seal.proof_term_hash[0..8].try_into().unwrap());
assert_ne!(encoded_hash, 0);
assert!(ledger.verify_integrity());
}
#[test]
fn test_mutation_ledger_integrity_after_compact() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(3);
for i in 0..3 {
ledger.append(create_attestation(&env, i));
}
assert!(ledger.verify_integrity());
ledger.compact();
assert!(ledger.verify_integrity());
for i in 10..13 {
ledger.append(create_attestation(&env, i));
}
assert!(ledger.verify_integrity());
}
#[test]
fn test_mutation_ledger_chain_hash_changes_on_append() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(100);
let h0 = ledger.chain_hash();
ledger.append(create_attestation(&env, 0));
let h1 = ledger.chain_hash();
assert_ne!(h0, h1);
ledger.append(create_attestation(&env, 1));
let h2 = ledger.chain_hash();
assert_ne!(h1, h2);
}
#[test]
fn test_mutation_ledger_epoch() {
let mut ledger = MutationLedger::new(100);
assert_eq!(ledger.epoch(), 0);
ledger.set_epoch(5);
assert_eq!(ledger.epoch(), 5);
}
#[test]
fn test_proof_scope_creation() {
let scope = ProofScope::new(42, vec![1, 2, 3], 100);
assert_eq!(scope.partition_id(), 42);
assert_eq!(scope.boundary_nodes(), &[1, 2, 3]);
assert!(scope.coherence().is_none());
assert!(scope.ledger().is_empty());
}
#[test]
fn test_proof_scope_coherence() {
let mut scope = ProofScope::new(1, vec![], 100);
assert!(scope.coherence().is_none());
scope.set_coherence(0.95);
assert_eq!(scope.coherence(), Some(0.95));
}
#[test]
fn test_proof_scope_ledger_access() {
let env = ProofEnvironment::new();
let mut scope = ProofScope::new(1, vec![10, 20], 100);
scope.ledger_mut().append(create_attestation(&env, 0));
scope.ledger_mut().append(create_attestation(&env, 1));
assert_eq!(scope.ledger().len(), 2);
assert!(scope.ledger().verify_integrity());
}
#[test]
fn test_proof_scope_transition() {
let env = ProofEnvironment::new();
let mut scope = ProofScope::new(1, vec![10, 20], 100);
scope.set_coherence(0.9);
scope.ledger_mut().append(create_attestation(&env, 0));
scope.ledger_mut().append(create_attestation(&env, 1));
let transition = scope.transition(2, vec![30, 40], 3.5);
assert_eq!(transition.old_partition_id, 1);
assert_eq!(transition.new_partition_id, 2);
assert_eq!(transition.min_cut_value, 3.5);
assert_eq!(transition.old_coherence, Some(0.9));
assert_eq!(scope.partition_id(), 2);
assert_eq!(scope.boundary_nodes(), &[30, 40]);
assert!(scope.coherence().is_none());
assert!(scope.ledger().is_empty());
}
#[test]
fn test_epoch_boundary_seal() {
let env = ProofEnvironment::new();
let mut ledger = MutationLedger::new(100);
for i in 0..5 {
ledger.append(create_attestation(&env, i));
}
assert_eq!(ledger.epoch(), 0);
let config = ProofEnvironmentConfig {
max_standard_fuel: 1000,
max_deep_steps: 20_000,
builtin_symbols: 128,
};
let boundary = EpochBoundary::seal(&mut ledger, config);
assert_eq!(boundary.from_epoch, 0);
assert_eq!(boundary.to_epoch, 1);
assert_eq!(boundary.new_config.max_standard_fuel, 1000);
assert_eq!(boundary.new_config.max_deep_steps, 20_000);
assert_eq!(boundary.new_config.builtin_symbols, 128);
assert_eq!(ledger.epoch(), 1);
assert_eq!(ledger.len(), 1);
assert!(ledger.verify_integrity());
}
#[test]
fn test_epoch_boundary_default_config() {
let config = ProofEnvironmentConfig::default();
assert_eq!(config.max_standard_fuel, 500);
assert_eq!(config.max_deep_steps, 10_000);
assert_eq!(config.builtin_symbols, 64);
}
#[test]
fn test_supersession_proof_creation() {
let env = ProofEnvironment::new();
let att = create_attestation(&env, 42);
let sp = SupersessionProof::new(7, att.clone(), 99);
assert_eq!(sp.superseded_position, 7);
assert_eq!(sp.soundness_proof_id, 99);
assert_eq!(
sp.replacement.content_hash(),
att.content_hash(),
);
}
#[test]
fn test_proof_requirement_to_proof_kind() {
let dim = ProofRequirement::DimensionMatch { expected: 128 };
assert!(matches!(dim.to_proof_kind(), ProofKind::DimensionEquality { .. }));
let ty = ProofRequirement::TypeMatch { schema_id: 1 };
assert!(matches!(ty.to_proof_kind(), ProofKind::TypeApplication { .. }));
let inv = ProofRequirement::InvariantPreserved { invariant_id: 5 };
assert!(matches!(inv.to_proof_kind(), ProofKind::Custom { .. }));
let coh = ProofRequirement::CoherenceBound { min_coherence: 0.8 };
assert!(matches!(coh.to_proof_kind(), ProofKind::Custom { .. }));
}
#[test]
fn test_proof_requirement_composite_routing() {
let comp_dim = ProofRequirement::Composite(vec![
ProofRequirement::DimensionMatch { expected: 64 },
ProofRequirement::DimensionMatch { expected: 128 },
]);
assert!(matches!(
comp_dim.to_proof_kind(),
ProofKind::DimensionEquality { .. }
));
let comp_ty = ProofRequirement::Composite(vec![
ProofRequirement::DimensionMatch { expected: 64 },
ProofRequirement::TypeMatch { schema_id: 1 },
]);
assert!(matches!(
comp_ty.to_proof_kind(),
ProofKind::TypeApplication { .. }
));
let comp_inv = ProofRequirement::Composite(vec![
ProofRequirement::TypeMatch { schema_id: 1 },
ProofRequirement::InvariantPreserved { invariant_id: 3 },
]);
assert!(matches!(comp_inv.to_proof_kind(), ProofKind::Custom { .. }));
}
#[test]
fn test_proof_requirement_leaf_count() {
let single = ProofRequirement::DimensionMatch { expected: 64 };
assert_eq!(single.leaf_count(), 1);
let composite = ProofRequirement::Composite(vec![
ProofRequirement::DimensionMatch { expected: 64 },
ProofRequirement::TypeMatch { schema_id: 1 },
ProofRequirement::Composite(vec![
ProofRequirement::InvariantPreserved { invariant_id: 1 },
ProofRequirement::CoherenceBound { min_coherence: 0.5 },
]),
]);
assert_eq!(composite.leaf_count(), 4);
}
#[test]
fn test_complexity_bound_fits_reflex() {
let reflex = ComplexityBound::new(5, 64, ComplexityClass::Constant);
assert!(reflex.fits_reflex());
assert!(reflex.fits_standard());
let too_many_ops =
ComplexityBound::new(20, 64, ComplexityClass::Constant);
assert!(!too_many_ops.fits_reflex());
let wrong_class =
ComplexityBound::new(5, 64, ComplexityClass::Linear);
assert!(!wrong_class.fits_reflex());
}
#[test]
fn test_complexity_bound_fits_standard() {
let standard =
ComplexityBound::new(500, 4096, ComplexityClass::Logarithmic);
assert!(standard.fits_standard());
let too_expensive =
ComplexityBound::new(501, 4096, ComplexityClass::Quadratic);
assert!(!too_expensive.fits_standard());
}
#[test]
fn test_proof_class_formal() {
let formal = ProofClass::Formal;
assert!(formal.is_formal());
assert!(!formal.is_statistical());
}
#[test]
fn test_proof_class_statistical() {
let stat = ProofClass::Statistical {
iterations: 10_000,
tolerance: 1e-9,
rng_seed: 42,
};
assert!(!stat.is_formal());
assert!(stat.is_statistical());
}
}