Skip to main content

airbender_host/
proof.rs

1use crate::error::Result;
2use crate::prover::ProverLevel;
3use crate::receipt::Receipt;
4use crate::security::SecurityLevel;
5use sha3::Digest;
6use std::path::Path;
7
8/// Wrapper around all proof flavors produced by host provers.
9#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
10#[allow(clippy::large_enum_variant)] // We don't want to optimize for the efficiency of the dev proof.
11pub enum Proof {
12    Dev(DevProof),
13    Real(RealProof),
14}
15
16impl Proof {
17    pub fn security(&self) -> SecurityLevel {
18        match self {
19            Self::Dev(proof) => proof.security,
20            Self::Real(proof) => proof.security,
21        }
22    }
23
24    pub fn debug_info(&self) -> String {
25        match self {
26            Self::Dev(proof) => format!(
27                "dev proof: security={} bits, cycles={}, output={:?}",
28                proof.security, proof.cycles, proof.receipt.output
29            ),
30            Self::Real(proof) => {
31                format!(
32                    "real proof: security={} bits, {}",
33                    proof.security,
34                    proof.inner.debug_info()
35                )
36            }
37        }
38    }
39}
40
41/// Development proof emitted by the transpiler-based prover.
42#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
43pub struct DevProof {
44    pub security: SecurityLevel,
45    pub app_bin_hash: [u8; 32],
46    pub input_words_hash: [u8; 32],
47    pub receipt: Receipt,
48    pub cycles: u64,
49}
50
51/// Real cryptographic proof emitted by CPU/GPU provers.
52#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
53pub struct RealProof {
54    security: SecurityLevel,
55    level: ProverLevel,
56    inner: execution_utils::unrolled::UnrolledProgramProof,
57}
58
59impl RealProof {
60    pub(crate) fn new(
61        security: SecurityLevel,
62        level: ProverLevel,
63        inner: execution_utils::unrolled::UnrolledProgramProof,
64    ) -> Self {
65        Self {
66            security,
67            level,
68            inner,
69        }
70    }
71
72    pub fn security(&self) -> SecurityLevel {
73        self.security
74    }
75
76    pub fn level(&self) -> ProverLevel {
77        self.level
78    }
79
80    /// Returns the wrapped unrolled proof.
81    ///
82    /// Using the raw proof directly is not recommended and is not covered by
83    /// the stable `airbender-host` public API. This is exposed for rare cases,
84    /// for example when a project depends on both `airbender-host` and direct
85    /// Airbender crates at the same time.
86    pub fn into_inner(self) -> execution_utils::unrolled::UnrolledProgramProof {
87        self.inner
88    }
89
90    pub(crate) fn inner(&self) -> &execution_utils::unrolled::UnrolledProgramProof {
91        &self.inner
92    }
93}
94
95pub(crate) fn hash_app_bin(path: &Path) -> Result<[u8; 32]> {
96    let bytes = std::fs::read(path)?;
97    Ok(sha3::Keccak256::digest(&bytes).into())
98}
99
100pub(crate) fn hash_input_words(input_words: &[u32]) -> [u8; 32] {
101    let mut hasher = sha3::Keccak256::new();
102    for word in input_words {
103        hasher.update(word.to_le_bytes());
104    }
105    hasher.finalize().into()
106}