pub mod error;
pub mod invariants;
pub mod vector_types;
pub mod proof_store;
pub mod pipeline;
#[cfg(feature = "fast-arena")]
pub mod fast_arena;
pub mod pools;
pub mod cache;
#[cfg(feature = "gated-proofs")]
pub mod gated;
pub use error::{VerificationError, Result};
pub use vector_types::{mk_vector_type, mk_nat_literal, prove_dim_eq};
pub use proof_store::ProofAttestation;
pub use pipeline::VerifiedStage;
pub use invariants::BuiltinDecl;
pub struct ProofEnvironment {
pub symbols: Vec<String>,
term_counter: u32,
proof_cache: std::collections::HashMap<u64, u32>,
pub stats: ProofStats,
}
#[derive(Debug, Clone, Default)]
pub struct ProofStats {
pub proofs_constructed: u64,
pub proofs_verified: u64,
pub cache_hits: u64,
pub cache_misses: u64,
pub total_reductions: u64,
}
impl ProofEnvironment {
pub fn new() -> Self {
let mut symbols = Vec::with_capacity(32);
invariants::register_builtin_symbols(&mut symbols);
Self {
symbols,
term_counter: 0,
proof_cache: std::collections::HashMap::with_capacity(256),
stats: ProofStats::default(),
}
}
pub fn alloc_term(&mut self) -> u32 {
let id = self.term_counter;
self.term_counter = self.term_counter.checked_add(1)
.ok_or_else(|| VerificationError::ArenaExhausted { allocated: id })
.expect("arena overflow");
self.stats.proofs_constructed += 1;
id
}
pub fn symbol_id(&self, name: &str) -> Option<usize> {
self.symbols.iter().position(|s| s == name)
}
pub fn require_symbol(&self, name: &str) -> Result<usize> {
self.symbol_id(name).ok_or_else(|| {
VerificationError::DeclarationNotFound { name: name.to_string() }
})
}
pub fn cache_lookup(&mut self, key: u64) -> Option<u32> {
if let Some(&id) = self.proof_cache.get(&key) {
self.stats.cache_hits += 1;
Some(id)
} else {
self.stats.cache_misses += 1;
None
}
}
pub fn cache_insert(&mut self, key: u64, proof_id: u32) {
self.proof_cache.insert(key, proof_id);
}
pub fn stats(&self) -> &ProofStats {
&self.stats
}
pub fn terms_allocated(&self) -> u32 {
self.term_counter
}
pub fn reset(&mut self) {
self.term_counter = 0;
self.proof_cache.clear();
self.stats = ProofStats::default();
self.symbols.clear();
invariants::register_builtin_symbols(&mut self.symbols);
}
}
impl Default for ProofEnvironment {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct VerifiedOp<T> {
pub value: T,
pub proof_id: u32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn proof_env_new_has_builtins() {
let env = ProofEnvironment::new();
assert!(env.symbol_id("Nat").is_some());
assert!(env.symbol_id("RuVec").is_some());
assert!(env.symbol_id("Eq").is_some());
assert!(env.symbol_id("Eq.refl").is_some());
assert!(env.symbol_id("HnswIndex").is_some());
}
#[test]
fn proof_env_alloc_term() {
let mut env = ProofEnvironment::new();
assert_eq!(env.alloc_term(), 0);
assert_eq!(env.alloc_term(), 1);
assert_eq!(env.alloc_term(), 2);
assert_eq!(env.terms_allocated(), 3);
}
#[test]
fn proof_env_cache() {
let mut env = ProofEnvironment::new();
assert!(env.cache_lookup(42).is_none());
env.cache_insert(42, 7);
assert_eq!(env.cache_lookup(42), Some(7));
assert_eq!(env.stats().cache_hits, 1);
assert_eq!(env.stats().cache_misses, 1);
}
#[test]
fn proof_env_reset() {
let mut env = ProofEnvironment::new();
env.alloc_term();
env.cache_insert(1, 2);
env.reset();
assert_eq!(env.terms_allocated(), 0);
assert!(env.cache_lookup(1).is_none());
assert!(env.symbol_id("Nat").is_some());
}
#[test]
fn proof_env_require_symbol() {
let env = ProofEnvironment::new();
assert!(env.require_symbol("Nat").is_ok());
assert!(env.require_symbol("NonExistent").is_err());
}
#[test]
fn verified_op_copy() {
let op = VerifiedOp { value: 42u32, proof_id: 1 };
let op2 = op; assert_eq!(op.value, op2.value);
}
}