airbender_host/prover/
mod.rs1use crate::error::{HostError, Result};
2use crate::proof::Proof;
3use crate::receipt::Receipt;
4use execution_utils::unrolled::UnrolledProgramProof;
5use std::path::{Path, PathBuf};
6
7mod cpu_prover;
8mod dev_prover;
9#[cfg(feature = "gpu-prover")]
10mod gpu_prover;
11
12pub use self::cpu_prover::{CpuProver, CpuProverBuilder};
13pub use self::dev_prover::{DevProver, DevProverBuilder};
14#[cfg(feature = "gpu-prover")]
15pub use self::gpu_prover::{GpuProver, GpuProverBuilder};
16
17pub(super) const DEFAULT_RAM_BOUND_BYTES: usize = 1 << 30;
18pub(super) const DEFAULT_CPU_CYCLE_BOUND: usize = u32::MAX as usize;
19
20pub trait Prover {
22 fn prove(&self, input_words: &[u32]) -> Result<ProveResult>;
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
27pub enum ProverLevel {
28 Base,
29 RecursionUnrolled,
30 #[default]
31 RecursionUnified,
32}
33
34impl ProverLevel {
35 #[cfg(feature = "gpu-prover")]
36 pub fn as_unrolled_level(self) -> execution_utils::unrolled_gpu::UnrolledProverLevel {
37 match self {
38 ProverLevel::Base => execution_utils::unrolled_gpu::UnrolledProverLevel::Base,
39 ProverLevel::RecursionUnrolled => {
40 execution_utils::unrolled_gpu::UnrolledProverLevel::RecursionUnrolled
41 }
42 ProverLevel::RecursionUnified => {
43 execution_utils::unrolled_gpu::UnrolledProverLevel::RecursionUnified
44 }
45 }
46 }
47}
48
49#[derive(Clone, Debug)]
51pub struct ProveResult {
52 pub proof: Proof,
53 pub cycles: u64,
54 pub receipt: Receipt,
55}
56
57pub(super) fn resolve_app_bin_path(path: &Path) -> Result<PathBuf> {
58 let base_path = base_path(path)?;
59 let app_bin_path = PathBuf::from(format!("{base_path}.bin"));
60
61 if !app_bin_path.exists() {
62 return Err(HostError::Prover(format!(
63 "binary not found: {}",
64 app_bin_path.display()
65 )));
66 }
67
68 app_bin_path.canonicalize().map_err(|err| {
69 HostError::Prover(format!(
70 "failed to canonicalize binary path {}: {err}",
71 app_bin_path.display()
72 ))
73 })
74}
75
76pub(super) fn resolve_text_path(app_bin_path: &Path) -> Result<PathBuf> {
77 let mut app_text_path = app_bin_path.to_path_buf();
78 app_text_path.set_extension("text");
79
80 if !app_text_path.exists() {
81 return Err(HostError::Prover(format!(
82 "text file not found: {}",
83 app_text_path.display()
84 )));
85 }
86
87 app_text_path.canonicalize().map_err(|err| {
88 HostError::Prover(format!(
89 "failed to canonicalize text path {}: {err}",
90 app_text_path.display()
91 ))
92 })
93}
94
95pub(super) fn base_path(app_bin_path: &Path) -> Result<String> {
96 let path_str = app_bin_path
97 .to_str()
98 .ok_or_else(|| HostError::Prover("app path is not valid UTF-8".to_string()))?;
99 if let Some(stripped) = path_str.strip_suffix(".bin") {
100 Ok(stripped.to_string())
101 } else {
102 Ok(path_str.to_string())
103 }
104}
105
106pub(super) fn resolve_worker_threads(worker_threads: Option<usize>) -> usize {
107 worker_threads
108 .or_else(|| {
109 std::thread::available_parallelism()
110 .ok()
111 .map(|count| count.get())
112 })
113 .unwrap_or(1)
114}
115
116pub(super) fn receipt_from_real_proof(proof: &UnrolledProgramProof) -> Receipt {
117 let mut registers = [0u32; 32];
118 for (idx, reg) in proof
119 .register_final_values
120 .iter()
121 .take(registers.len())
122 .enumerate()
123 {
124 registers[idx] = reg.value;
125 }
126 Receipt::from_registers(registers)
127}