light_prover_client/
prover.rs1use std::{
2 fmt::{Display, Formatter},
3 process::Command,
4 sync::atomic::{AtomicBool, Ordering},
5 thread::sleep,
6 time::Duration,
7};
8
9use tracing::info;
10
11use crate::{
12 constants::{HEALTH_CHECK, SERVER_ADDRESS},
13 helpers::get_project_root,
14 proof_type::ProofType,
15};
16
17static IS_LOADING: AtomicBool = AtomicBool::new(false);
18#[derive(Debug, Clone, Copy, PartialEq)]
19pub enum ProverMode {
20 Rpc,
21 Forester,
22 ForesterTest,
23 Full,
24 FullTest,
25}
26
27impl Display for ProverMode {
28 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29 write!(
30 f,
31 "{}",
32 match self {
33 ProverMode::Rpc => "rpc",
34 ProverMode::Forester => "forester",
35 ProverMode::ForesterTest => "forester-test",
36 ProverMode::Full => "full",
37 ProverMode::FullTest => "full-test",
38 }
39 )
40 }
41}
42
43#[derive(Debug, Clone)]
44pub struct ProverConfig {
45 pub run_mode: Option<ProverMode>,
46 pub circuits: Vec<ProofType>,
47}
48
49impl Default for ProverConfig {
50 #[cfg(feature = "devenv")]
51 fn default() -> Self {
52 Self {
53 run_mode: Some(ProverMode::ForesterTest),
54 circuits: vec![],
55 }
56 }
57 #[cfg(not(feature = "devenv"))]
58 fn default() -> Self {
59 Self {
60 run_mode: Some(ProverMode::Rpc),
61 circuits: vec![],
62 }
63 }
64}
65
66impl ProverConfig {
67 pub fn rpc_no_restart() -> Self {
68 Self {
69 run_mode: Some(ProverMode::Rpc),
70 circuits: vec![],
71 }
72 }
73}
74
75pub async fn spawn_prover(config: ProverConfig) {
76 if let Some(_project_root) = get_project_root() {
77 let prover_path: &str = {
78 #[cfg(feature = "devenv")]
79 {
80 &format!("{}/{}", _project_root.trim(), "cli/test_bin/run")
81 }
82 #[cfg(not(feature = "devenv"))]
83 {
84 println!("Running in production mode, using prover binary");
85 "light"
86 }
87 };
88
89 if !health_check(10, 1).await && !IS_LOADING.load(Ordering::Relaxed) {
90 IS_LOADING.store(true, Ordering::Relaxed);
91
92 let mut command = Command::new(prover_path);
93 command.arg("start-prover");
94
95 if let Some(ref mode) = config.run_mode {
96 command.arg("--run-mode").arg(mode.to_string());
97 }
98
99 for circuit in config.circuits.clone() {
100 command.arg("--circuit").arg(circuit.to_string());
101 }
102
103 println!("Starting prover with command: {:?}", command);
104
105 let _ = command
106 .spawn()
107 .expect("Failed to start prover process")
108 .wait();
109
110 let health_result = health_check(120, 1).await;
111 if health_result {
112 info!("Prover started successfully");
113 } else {
114 panic!("Failed to start prover, health check failed.");
115 }
116 }
117 #[cfg(not(feature = "devenv"))]
118 {
119 "light"
120 }
121 } else {
122 panic!("Failed to find project root.");
123 };
124}
125
126pub async fn health_check(retries: usize, timeout: usize) -> bool {
127 let client = reqwest::Client::new();
128 let mut result = false;
129 for _ in 0..retries {
130 match client
131 .get(format!("{}{}", SERVER_ADDRESS, HEALTH_CHECK))
132 .send()
133 .await
134 {
135 Ok(_) => {
136 result = true;
137 break;
138 }
139 Err(_) => {
140 sleep(Duration::from_secs(timeout as u64));
141 }
142 }
143 }
144 result
145}