oxilean_kernel/proof_cert/types.rs
1//! Types for the Proof Certificate System.
2//!
3//! A proof certificate is a compact, checkable record that a term has been verified.
4//! Certificates enable exporting/importing proofs without re-checking from scratch.
5
6use std::collections::HashMap;
7
8/// Unique identifier for a proof certificate.
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10pub struct ProofCertId(pub u64);
11
12impl ProofCertId {
13 /// Create a new certificate ID from a raw value.
14 pub fn new(id: u64) -> Self {
15 ProofCertId(id)
16 }
17
18 /// Get the raw numeric value.
19 pub fn raw(self) -> u64 {
20 self.0
21 }
22}
23
24impl std::fmt::Display for ProofCertId {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 write!(f, "cert#{}", self.0)
27 }
28}
29
30/// A single step in a proof reduction sequence.
31///
32/// These steps record the high-level reduction moves taken during kernel
33/// type-checking, enabling efficient replay or auditing.
34#[derive(Clone, Debug, PartialEq, Eq)]
35pub enum ProofStep {
36 /// β-reduction: substitute the argument into the body.
37 ///
38 /// `redex_depth` records the nesting depth at which this reduction occurred.
39 Beta {
40 /// De Bruijn depth of the beta-redex site.
41 redex_depth: u32,
42 },
43 /// δ-reduction: unfold a named definition.
44 Delta {
45 /// Name of the definition that was unfolded.
46 name: String,
47 },
48 /// ζ-reduction: substitute a let-binding.
49 Zeta,
50 /// ι-reduction: reduce a recursor application to a branch.
51 Iota {
52 /// Name of the recursor that fired.
53 recursor: String,
54 /// Index of the constructor branch selected.
55 ctor_idx: u32,
56 },
57 /// η-reduction: contract `λ x, f x` to `f`.
58 Eta,
59 /// Universe-level substitution.
60 SubstLevel {
61 /// Parameter names substituted.
62 params: Vec<String>,
63 },
64 /// Appeal to a local assumption (hypothesis) in the context.
65 Assumption,
66}
67
68impl std::fmt::Display for ProofStep {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 match self {
71 ProofStep::Beta { redex_depth } => write!(f, "Beta(depth={})", redex_depth),
72 ProofStep::Delta { name } => write!(f, "Delta({})", name),
73 ProofStep::Zeta => write!(f, "Zeta"),
74 ProofStep::Iota { recursor, ctor_idx } => {
75 write!(f, "Iota({}, ctor={})", recursor, ctor_idx)
76 }
77 ProofStep::Eta => write!(f, "Eta"),
78 ProofStep::SubstLevel { params } => write!(f, "SubstLevel({:?})", params),
79 ProofStep::Assumption => write!(f, "Assumption"),
80 }
81 }
82}
83
84/// A compact verification record for a single declaration.
85///
86/// Certificates record the structural hashes of the type and proof term, together
87/// with the sequence of reduction steps performed during kernel type-checking.
88/// They can be stored externally and replayed cheaply via hash verification.
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct ProofCertificate {
91 /// Unique certificate identifier (derived from content at creation time).
92 pub id: ProofCertId,
93 /// Name of the declaration this certificate vouches for.
94 pub decl_name: String,
95 /// FNV-1a structural hash of the declaration's type expression.
96 pub type_hash: u64,
97 /// FNV-1a structural hash of the proof term expression.
98 pub proof_hash: u64,
99 /// Ordered sequence of reduction steps taken during type-checking.
100 pub reduction_steps: Vec<ProofStep>,
101 /// Unix timestamp (seconds) at which the certificate was created.
102 pub verified_at: u64,
103}
104
105impl ProofCertificate {
106 /// Return the number of reduction steps recorded.
107 pub fn step_count(&self) -> usize {
108 self.reduction_steps.len()
109 }
110
111 /// Return true if this certificate records no reduction steps.
112 pub fn is_trivial(&self) -> bool {
113 self.reduction_steps.is_empty()
114 }
115}
116
117impl std::fmt::Display for ProofCertificate {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 write!(
120 f,
121 "ProofCert {{ id: {}, decl: {}, type_hash: {:016x}, proof_hash: {:016x}, steps: {} }}",
122 self.id,
123 self.decl_name,
124 self.type_hash,
125 self.proof_hash,
126 self.reduction_steps.len()
127 )
128 }
129}
130
131/// Persistent store of proof certificates, keyed by declaration name.
132#[derive(Clone, Debug, Default)]
133pub struct CertificateStore {
134 /// Map from declaration name to its certificate.
135 pub certs: HashMap<String, ProofCertificate>,
136}
137
138impl CertificateStore {
139 /// Create an empty certificate store.
140 pub fn new() -> Self {
141 CertificateStore {
142 certs: HashMap::new(),
143 }
144 }
145
146 /// Return the number of certificates in the store.
147 pub fn len(&self) -> usize {
148 self.certs.len()
149 }
150
151 /// Return true if the store is empty.
152 pub fn is_empty(&self) -> bool {
153 self.certs.is_empty()
154 }
155
156 /// Iterate over all (name, certificate) pairs.
157 pub fn iter(&self) -> impl Iterator<Item = (&String, &ProofCertificate)> {
158 self.certs.iter()
159 }
160}
161
162/// The result of checking a proof certificate against a live environment.
163#[derive(Clone, Debug, PartialEq, Eq)]
164pub enum CertCheckResult {
165 /// The certificate is consistent with the environment.
166 Valid,
167 /// The stored hash does not match the recomputed hash.
168 HashMismatch {
169 /// The hash stored in the certificate.
170 expected: u64,
171 /// The hash recomputed from the environment.
172 actual: u64,
173 },
174 /// The declaration named in the certificate is absent from the environment.
175 MissingDecl(String),
176 /// The reduction steps are internally inconsistent or ill-formed.
177 InvalidSteps,
178}
179
180impl std::fmt::Display for CertCheckResult {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 CertCheckResult::Valid => write!(f, "Valid"),
184 CertCheckResult::HashMismatch { expected, actual } => {
185 write!(
186 f,
187 "HashMismatch {{ expected: {:016x}, actual: {:016x} }}",
188 expected, actual
189 )
190 }
191 CertCheckResult::MissingDecl(name) => write!(f, "MissingDecl({})", name),
192 CertCheckResult::InvalidSteps => write!(f, "InvalidSteps"),
193 }
194 }
195}