Skip to content

Commit c3eb626

Browse files
authored
zkboost support mock zkvm (#35)
* feat: add mock zkVM support in `zkboost-server` * chore: loops to get chain config * feat: add `mocknet` deployment example * feat: add `GET /health` endpoint for EWS * fix: verify test
1 parent 423db5c commit c3eb626

File tree

15 files changed

+235
-78
lines changed

15 files changed

+235
-78
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ futures = "0.3"
4848
indexmap = "2.12"
4949
lru = "0.12"
5050
nix = "0.29"
51+
rand = "0.9.2"
5152
reqwest = "0.12"
5253
serde = "1.0"
5354
serde_json = "1"

crates/execution-witness-sentry/src/main.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
//! Relayer for execution proof.
1+
//! Execution witness sentry (EWS).
22
//!
3-
//! This relayer orchestrates the complete workflow for generating proofs of
4-
//! execution proof:
3+
//! EWS orchestrates the complete workflow for generating proofs of execution proof:
54
//!
65
//! 1. Listen to new block from CL
76
//! 2. Fetch execution witness from EL
@@ -12,7 +11,7 @@
1211
//! ## Architecture
1312
//!
1413
//! ```text
15-
//! CL Relayer EL Proof Engine
14+
//! CL EWS EL Proof Engine
1615
//! | | | |
1716
//! |--new block-->| | |
1817
//! | | | |
@@ -31,7 +30,7 @@
3130
//! | | | |
3231
//! ```
3332
34-
use std::{num::NonZeroUsize, path::PathBuf, sync::Arc};
33+
use std::{num::NonZeroUsize, path::PathBuf, sync::Arc, time::Duration};
3534

3635
use anyhow::bail;
3736
use clap::Parser;
@@ -50,6 +49,7 @@ use lru::LruCache;
5049
use tokio::{
5150
signal::unix::{SignalKind, signal},
5251
sync::Mutex,
52+
time::sleep,
5353
};
5454
use tokio_util::sync::CancellationToken;
5555
use tracing::{info, warn};
@@ -99,21 +99,19 @@ async fn main() -> anyhow::Result<()> {
9999

100100
// Get chain config.
101101

102-
let mut chain_config = None;
103-
for el_client in &el_clients {
104-
if let Ok(Some(c)) = el_client.get_chain_config().await {
105-
chain_config = Some(c);
106-
break;
107-
} else {
102+
let chain_config = 'outer: loop {
103+
for el_client in &el_clients {
104+
if let Ok(Some(chain_config)) = el_client.get_chain_config().await {
105+
break 'outer chain_config;
106+
}
108107
warn!(
109108
name = %el_client.name(),
110109
url = %el_client.url(),
111110
"Failed to get chain config",
112111
)
113-
};
114-
}
115-
let Some(chain_config) = chain_config else {
116-
bail!("Failed to get chain config from any EL endpoint");
112+
}
113+
114+
sleep(Duration::from_secs(2)).await;
117115
};
118116

119117
// Initialize CL clients.
@@ -137,7 +135,7 @@ async fn main() -> anyhow::Result<()> {
137135
}
138136
}
139137
Err(e) => {
140-
warn!(name = %endpoint.name, error = %e, "Failed to check zkvm status");
138+
warn!(name = %endpoint.name, error = %e, "Failed to check if client has zkVM enabled or not");
141139
}
142140
}
143141
}

crates/execution-witness-sentry/src/service/proof.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ use std::{
3333

3434
use alloy_genesis::ChainConfig;
3535
use alloy_primitives::B256;
36-
use axum::{Json, Router, extract::State, http::StatusCode, routing::post};
36+
use axum::{
37+
Json, Router,
38+
extract::State,
39+
http::StatusCode,
40+
routing::{get, post},
41+
};
3742
use lru::LruCache;
3843
use reth_stateless::StatelessInput;
3944
use tokio::{
@@ -691,6 +696,7 @@ async fn spawn_webhook_server(
691696
Ok(tokio::spawn(async move {
692697
let app = Router::new()
693698
.route("/proofs", post(proof_webhook))
699+
.route("/health", get(StatusCode::OK))
694700
.with_state(state)
695701
.layer(TraceLayer::new_for_http())
696702
// 10MB limit to account for the proof size

crates/zkboost/server-config/src/config.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ pub enum zkVMConfig {
104104
/// Unique identifier for this program.
105105
program_id: ProgramID,
106106
},
107+
/// Mock zkVM configuration
108+
Mock {
109+
/// Mock time in millisecond for proof generation.
110+
mock_proving_time_ms: u64,
111+
/// Mock size for proof.
112+
mock_proof_size: u64,
113+
/// Unique identifier for this program.
114+
program_id: ProgramID,
115+
},
107116
}
108117

109118
impl zkVMConfig {
@@ -112,6 +121,7 @@ impl zkVMConfig {
112121
match self {
113122
Self::Docker { program_id, .. } => program_id,
114123
Self::External { program_id, .. } => program_id,
124+
Self::Mock { program_id, .. } => program_id,
115125
}
116126
}
117127
}
@@ -150,6 +160,11 @@ mod test {
150160
[[zkvm]]
151161
endpoint = "http://remote:3000"
152162
program_id = "external-test"
163+
164+
[[zkvm]]
165+
mock_proving_time_ms = 1000
166+
mock_proof_size = 1024
167+
program_id = "mock"
153168
"#;
154169
assert_eq!(Config::from_toml_str(toml).unwrap(), sample_config());
155170
}
@@ -178,6 +193,9 @@ mod test {
178193
url: http://artifact
179194
- endpoint: "http://remote:3000"
180195
program_id: "external-test"
196+
- mock_proving_time_ms: 1000
197+
mock_proof_size: 1024
198+
program_id: "mock"
181199
"#;
182200
assert_eq!(Config::from_yaml_str(yaml).unwrap(), sample_config());
183201
}
@@ -216,6 +234,11 @@ mod test {
216234
endpoint: "http://remote:3000".to_string(),
217235
program_id: "external-test".into(),
218236
},
237+
zkVMConfig::Mock {
238+
mock_proving_time_ms: 1000,
239+
mock_proof_size: 1 << 10,
240+
program_id: "mock".into(),
241+
},
219242
],
220243
}
221244
}

crates/zkboost/server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ anyhow.workspace = true
1313
axum = { workspace = true, features = ["macros"] }
1414
clap = { workspace = true, features = ["derive"] }
1515
futures.workspace = true
16+
rand.workspace = true
1617
reqwest = { workspace = true, features = ["json"] }
1718
sysinfo.workspace = true
1819
tokio = { workspace = true, features = ["full"] }

crates/zkboost/server/src/app.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::{
2727
execute::execute_program, info::get_server_info, prove::prove_program, verify::verify_proof,
2828
},
2929
metrics::http_metrics_middleware,
30+
mock::MockzkVM,
3031
proof_service::{ProofMessage, ProofService},
3132
};
3233

@@ -97,8 +98,7 @@ pub(crate) enum zkVMInstance {
9798
client: Arc<zkVMClient>,
9899
},
99100
/// Mock zkVM
100-
#[cfg(test)]
101-
Mock(crate::mock::MockzkVM),
101+
Mock(MockzkVM),
102102
}
103103

104104
impl zkVMInstance {
@@ -118,6 +118,11 @@ impl zkVMInstance {
118118
})
119119
}
120120

121+
/// Creates an mock zkVM instance.
122+
pub(crate) fn mock(mock_proving_time_ms: u64, mock_proof_size: u64) -> Self {
123+
Self::Mock(MockzkVM::new(mock_proving_time_ms, mock_proof_size))
124+
}
125+
121126
/// Executes the program with the given input.
122127
pub(crate) async fn execute(
123128
&self,
@@ -126,8 +131,7 @@ impl zkVMInstance {
126131
match self {
127132
Self::Docker { vm } => vm.execute_async(input).await,
128133
Self::External { client } => Ok(client.execute(input).await?),
129-
#[cfg(test)]
130-
Self::Mock(vm) => vm.execute(&input),
134+
Self::Mock(vm) => vm.execute(&input).await,
131135
}
132136
}
133137

@@ -140,8 +144,7 @@ impl zkVMInstance {
140144
match self {
141145
Self::Docker { vm } => vm.prove_async(input, proof_kind).await,
142146
Self::External { client } => Ok(client.prove(input, proof_kind).await?),
143-
#[cfg(test)]
144-
Self::Mock(vm) => vm.prove(&input, proof_kind),
147+
Self::Mock(vm) => vm.prove(&input, proof_kind).await,
145148
}
146149
}
147150

@@ -151,8 +154,7 @@ impl zkVMInstance {
151154
match self {
152155
Self::Docker { vm } => vm.verify_async(proof).await,
153156
Self::External { client } => Ok(client.verify(proof).await?),
154-
#[cfg(test)]
155-
Self::Mock(vm) => vm.verify(&proof),
157+
Self::Mock(vm) => vm.verify(&proof).await,
156158
}
157159
}
158160
}
@@ -194,5 +196,10 @@ async fn init_zkvm(config: &zkVMConfig) -> anyhow::Result<zkVMInstance> {
194196
Ok(zkVMInstance::docker(zkvm))
195197
}
196198
zkVMConfig::External { endpoint, .. } => zkVMInstance::external(endpoint.clone()).await,
199+
zkVMConfig::Mock {
200+
mock_proving_time_ms,
201+
mock_proof_size,
202+
..
203+
} => Ok(zkVMInstance::mock(*mock_proving_time_ms, *mock_proof_size)),
197204
}
198205
}

crates/zkboost/server/src/app/execute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ mod tests {
5454
use axum::{Json, extract::State, http::StatusCode};
5555
use zkboost_types::{ExecuteRequest, ProgramID};
5656

57-
use crate::{app::execute::execute_program, mock::mock_app_state};
57+
use crate::{app::execute::execute_program, mock::tests::mock_app_state};
5858

5959
#[tokio::test]
6060
async fn test_execute_success() {

crates/zkboost/server/src/app/prove.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ mod tests {
4242
use axum::{Json, extract::State, http::StatusCode};
4343
use zkboost_types::{ProgramID, ProveRequest};
4444

45-
use crate::{app::prove::prove_program, mock::mock_app_state};
45+
use crate::{app::prove::prove_program, mock::tests::mock_app_state};
4646

4747
#[tokio::test]
4848
async fn test_prove_success() {

crates/zkboost/server/src/app/verify.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,24 @@ mod tests {
5656
use axum::{Json, extract::State, http::StatusCode};
5757
use zkboost_types::{ProgramID, VerifyRequest};
5858

59-
use crate::{app::verify::verify_proof, mock::mock_app_state};
59+
use crate::{
60+
app::{verify::verify_proof, zkVMInstance},
61+
mock::tests::mock_app_state,
62+
};
6063

6164
#[tokio::test]
6265
async fn test_verify_valid_proof() {
6366
let program_id = ProgramID::from("mock_program_id");
6467
let state = mock_app_state(Some(&program_id));
6568

69+
let zkVMInstance::Mock(zkvm) = &state.programs[&program_id] else {
70+
unreachable!()
71+
};
72+
6673
// Create a request with the mock proof that MockzkVM accepts
6774
let request = VerifyRequest {
6875
program_id: program_id.clone(),
69-
proof: b"mock_proof".to_vec(),
76+
proof: zkvm.random_proof(),
7077
};
7178

7279
// Call the handler

0 commit comments

Comments
 (0)