fuse_core/
proof.rs

1//! Zero-knowledge proof structures and operations
2
3use serde::{Deserialize, Serialize};
4use crate::error::Result;
5
6/// Result of a compliance check
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum ComplianceResult {
9    Pass = 0,
10    Fail = 1,
11}
12
13/// The complete output committed to the journal by the guest
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct JournalOutput {
16    pub result: ComplianceResult,
17    // Use empty vec instead of Option to avoid serialization issues
18    pub claim_hash: Vec<u8>,
19    // Serialize JSON as string to avoid RISC Zero journal format issues
20    pub redacted_json: String,
21}
22
23impl std::fmt::Display for ComplianceResult {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        match self {
26            ComplianceResult::Pass => write!(f, "PASS"),
27            ComplianceResult::Fail => write!(f, "FAIL"),
28        }
29    }
30}
31
32/// Zero-knowledge proof of compliance check execution
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct ComplianceProof {
35    /// The proof data (RISC Zero receipt or similar)
36    /// In production, this would be a binary proof blob
37    /// For MVP, we use a placeholder structure
38    pub proof_data: Vec<u8>,
39
40    /// Hash of the specification that was verified
41    pub spec_hash: String,
42
43    /// Result of the compliance check
44    pub result: ComplianceResult,
45
46    /// Timestamp when the proof was generated
47    pub timestamp: chrono::DateTime<chrono::Utc>,
48
49    /// RISC Zero journal (public outputs from zkVM execution)
50    pub journal: Vec<u8>,
51
52    /// Decoded journal output
53    pub journal_output: Option<JournalOutput>,
54}
55
56impl ComplianceProof {
57    /// Create a new proof from a RISC Zero receipt
58    #[must_use] 
59    pub fn from_risc_zero_receipt(
60        spec_hash: String,
61        receipt_bytes: Vec<u8>,
62        journal_output: JournalOutput,
63        journal: Vec<u8>,
64    ) -> Self {
65        Self {
66            proof_data: receipt_bytes,
67            spec_hash,
68            result: journal_output.result,
69            timestamp: chrono::Utc::now(),
70            journal,
71            journal_output: Some(journal_output),
72        }
73    }
74
75    /// Create a new proof (placeholder for MVP)
76    /// In production, this would generate an actual RISC Zero proof
77    #[must_use] 
78    pub fn new(
79        spec_hash: String,
80        result: ComplianceResult,
81        journal: Vec<u8>,
82    ) -> Self {
83        Self {
84            // Placeholder: In production, this would contain the actual RISC Zero proof
85            proof_data: vec![],
86            spec_hash,
87            result,
88            timestamp: chrono::Utc::now(),
89            journal,
90            journal_output: None,
91        }
92    }
93    
94    /// Check if this is a placeholder proof (empty `proof_data`) or a real proof
95    #[must_use] 
96    pub fn is_placeholder(&self) -> bool {
97        self.proof_data.is_empty()
98    }
99
100    /// Verify the proof
101    /// In production, this would use RISC Zero's verifier
102    pub fn verify(&mut self) -> Result<()> {
103        // If this is a placeholder proof, allow it for backward compatibility
104        if self.is_placeholder() {
105            return Ok(());
106        }
107
108        // For real proofs, verify using RISC Zero
109        let (output, _) = crate::zkvm::verify_proof(&self.proof_data)?;
110        self.journal_output = Some(output);
111        Ok(())
112    }
113
114    /// Check if the proof is valid and the result is Pass
115    pub fn is_valid_pass(&mut self) -> Result<bool> {
116        self.verify()?;
117        Ok(self.result == ComplianceResult::Pass)
118    }
119}
120