Skip to content

Commit 7f64cbe

Browse files
smtmfftjohntaikoctian1
authored
feat(raiko): merge stress test upgrades (#392)
* update risc0-zkvm to v1.1.2 * use async sleep to avoid deadlock * update docker build * verify zk proof by default * update to sp1-sdk 3.0.0 * fix: print error in run_task * update patches (#388) * fix typo * fix stress test merge issues * fix sp1 verification fixture format * fix risc0 verification * update env script --------- Co-authored-by: john xu <[email protected]> Co-authored-by: Chris T. <[email protected]>
1 parent 8471b16 commit 7f64cbe

19 files changed

+631
-502
lines changed

Cargo.lock

+306-334
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4-5
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,12 @@ reth-chainspec = { git = "https://github.com/taikoxyz/taiko-reth.git", branch =
5353
reth-provider = { git = "https://github.com/taikoxyz/taiko-reth.git", branch = "v1.0.0-rc.2-taiko", default-features = false }
5454

5555
# risc zero
56-
risc0-zkvm = { version = "1.0.1", features = ["prove", "getrandom"] }
57-
bonsai-sdk = { version = "0.8.0", features = ["async"] }
58-
risc0-build = { version = "1.0.1" }
59-
risc0-binfmt = { version = "1.0.1" }
56+
risc0-zkvm = { version = "=1.1.2", features = ["prove", "getrandom"] }
57+
bonsai-sdk = { version = "=1.1.2" }
58+
risc0-binfmt = { version = "=1.1.2" }
6059

6160
# SP1
62-
sp1-sdk = { version = "2.0.0" }
61+
sp1-sdk = { version = "=3.0.0-rc3" }
6362
sp1-zkvm = { version = "2.0.0" }
6463
sp1-helper = { version = "2.0.0" }
6564

Dockerfile.zk

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ RUN echo "Building for sp1"
4040
ENV TARGET=sp1
4141
RUN make install
4242
RUN make guest
43-
RUN cargo build --release ${BUILD_FLAGS} --features "sp1,risc0,bonsai-auto-scaling" --features "docker_build"
43+
RUN cargo build --release ${BUILD_FLAGS} --features "sp1,risc0" --features "docker_build"
4444

4545
RUN mkdir -p \
4646
./bin \

docker/docker-compose.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,11 @@ services:
130130
volumes:
131131
- /var/log/raiko:/var/log/raiko
132132
ports:
133-
- "8081:8080"
133+
- "8080:8080"
134134
environment:
135135
# you can use your own PCCS host
136136
# - PCCS_HOST=host.docker.internal:8081
137+
- RUST_LOG=${RUST_LOG:-info}
137138
- ZK=true
138139
- ETHEREUM_RPC=${ETHEREUM_RPC}
139140
- ETHEREUM_BEACON_RPC=${ETHEREUM_BEACON_RPC}
@@ -145,11 +146,13 @@ services:
145146
- NETWORK=${NETWORK}
146147
- BONSAI_API_KEY=${BONSAI_API_KEY}
147148
- BONSAI_API_URL=${BONSAI_API_URL}
148-
- MAX_BONSAI_GPU_NUM=15
149+
- MAX_BONSAI_GPU_NUM=300
149150
- GROTH16_VERIFIER_RPC_URL=${GROTH16_VERIFIER_RPC_URL}
150151
- GROTH16_VERIFIER_ADDRESS=${GROTH16_VERIFIER_ADDRESS}
151152
- SP1_PRIVATE_KEY=${SP1_PRIVATE_KEY}
152153
- SKIP_SIMULATION=true
154+
- SP1_VERIFIER_RPC_URL=${SP1_VERIFIER_RPC_URL}
155+
- SP1_VERIFIER_ADDRESS=${SP1_VERIFIER_ADDRESS}
153156
pccs:
154157
build:
155158
context: ..

host/src/proof.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,18 @@ impl ProofActor {
105105
pub async fn run_task(&mut self, proof_request: ProofRequest) {
106106
let cancel_token = CancellationToken::new();
107107

108-
let Ok((chain_id, blockhash)) = get_task_data(
108+
let (chain_id, blockhash) = match get_task_data(
109109
&proof_request.network,
110110
proof_request.block_number,
111111
&self.chain_specs,
112112
)
113113
.await
114-
else {
115-
error!("Could not get task data for {proof_request:?}");
116-
return;
114+
{
115+
Ok(v) => v,
116+
Err(e) => {
117+
error!("Could not get task data for {proof_request:?}, error: {e}");
118+
return;
119+
}
117120
};
118121

119122
let key = TaskDescriptor::from((

provers/risc0/driver/src/bonsai.rs

+39-21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
Risc0Response,
55
};
66
use alloy_primitives::B256;
7+
use bonsai_sdk::blocking::{Client, SessionId};
78
use log::{debug, error, info, warn};
89
use raiko_lib::{
910
primitives::keccak::keccak,
@@ -19,14 +20,17 @@ use std::{
1920
fs,
2021
path::{Path, PathBuf},
2122
};
23+
use tokio::time::{sleep as tokio_async_sleep, Duration};
2224

2325
use crate::Risc0Param;
2426

27+
const MAX_REQUEST_RETRY: usize = 8;
28+
2529
#[derive(thiserror::Error, Debug)]
2630
pub enum BonsaiExecutionError {
2731
// common errors: include sdk error, or some others from non-bonsai code
2832
#[error(transparent)]
29-
SdkFailure(#[from] bonsai_sdk::alpha::SdkErr),
33+
SdkFailure(#[from] bonsai_sdk::SdkErr),
3034
#[error("bonsai execution error: {0}")]
3135
Other(String),
3236
// critical error like OOM, which is un-recoverable
@@ -44,12 +48,12 @@ pub async fn verify_bonsai_receipt<O: Eq + Debug + DeserializeOwned>(
4448
max_retries: usize,
4549
) -> Result<(String, Receipt), BonsaiExecutionError> {
4650
info!("Tracking receipt uuid: {uuid}");
47-
let session = bonsai_sdk::alpha::SessionId { uuid };
51+
let session = SessionId { uuid };
4852

4953
loop {
5054
let mut res = None;
5155
for attempt in 1..=max_retries {
52-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
56+
let client = Client::from_env(risc0_zkvm::VERSION)?;
5357

5458
match session.status(&client) {
5559
Ok(response) => {
@@ -61,7 +65,7 @@ pub async fn verify_bonsai_receipt<O: Eq + Debug + DeserializeOwned>(
6165
return Err(BonsaiExecutionError::SdkFailure(err));
6266
}
6367
warn!("Attempt {attempt}/{max_retries} for session status request: {err:?}");
64-
std::thread::sleep(std::time::Duration::from_secs(15));
68+
tokio_async_sleep(Duration::from_secs(15)).await;
6569
continue;
6670
}
6771
}
@@ -72,17 +76,18 @@ pub async fn verify_bonsai_receipt<O: Eq + Debug + DeserializeOwned>(
7276

7377
if res.status == "RUNNING" {
7478
info!(
75-
"Current status: {} - state: {} - continue polling...",
79+
"Current {session:?} status: {} - state: {} - continue polling...",
7680
res.status,
7781
res.state.unwrap_or_default()
7882
);
79-
std::thread::sleep(std::time::Duration::from_secs(15));
83+
tokio_async_sleep(Duration::from_secs(15)).await;
8084
} else if res.status == "SUCCEEDED" {
8185
// Download the receipt, containing the output
86+
info!("Prove task {session:?} success.");
8287
let receipt_url = res
8388
.receipt_url
8489
.expect("API error, missing receipt on completed session");
85-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
90+
let client = Client::from_env(risc0_zkvm::VERSION)?;
8691
let receipt_buf = client.download(&receipt_url)?;
8792
let receipt: Receipt = bincode::deserialize(&receipt_buf).map_err(|e| {
8893
BonsaiExecutionError::Other(format!("Failed to deserialize receipt: {e:?}"))
@@ -104,10 +109,10 @@ pub async fn verify_bonsai_receipt<O: Eq + Debug + DeserializeOwned>(
104109
}
105110
return Ok((session.uuid, receipt));
106111
} else {
107-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
112+
let client = Client::from_env(risc0_zkvm::VERSION)?;
108113
let bonsai_err_log = session.logs(&client);
109114
return Err(BonsaiExecutionError::Fatal(format!(
110-
"Workflow exited: {} - | err: {} | log: {bonsai_err_log:?}",
115+
"Workflow {session:?} exited: {} - | err: {} | log: {bonsai_err_log:?}",
111116
res.status,
112117
res.error_msg.unwrap_or_default(),
113118
)));
@@ -167,11 +172,11 @@ pub async fn maybe_prove<I: Serialize, O: Eq + Debug + Serialize + DeserializeOw
167172
}
168173
Err(BonsaiExecutionError::SdkFailure(err)) => {
169174
warn!("Bonsai SDK fail: {err:?}, keep tracking...");
170-
std::thread::sleep(std::time::Duration::from_secs(15));
175+
tokio_async_sleep(Duration::from_secs(15)).await;
171176
}
172177
Err(BonsaiExecutionError::Other(err)) => {
173178
warn!("Something wrong: {err:?}, keep tracking...");
174-
std::thread::sleep(std::time::Duration::from_secs(15));
179+
tokio_async_sleep(Duration::from_secs(15)).await;
175180
}
176181
Err(BonsaiExecutionError::Fatal(err)) => {
177182
error!("Fatal error on Bonsai: {err:?}");
@@ -228,13 +233,13 @@ pub async fn maybe_prove<I: Serialize, O: Eq + Debug + Serialize + DeserializeOw
228233
}
229234

230235
pub async fn upload_receipt(receipt: &Receipt) -> anyhow::Result<String> {
231-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
236+
let client = Client::from_env(risc0_zkvm::VERSION)?;
232237
Ok(client.upload_receipt(bincode::serialize(receipt)?)?)
233238
}
234239

235240
pub async fn cancel_proof(uuid: String) -> anyhow::Result<()> {
236-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
237-
let session = bonsai_sdk::alpha::SessionId { uuid };
241+
let client = Client::from_env(risc0_zkvm::VERSION)?;
242+
let session = SessionId { uuid };
238243
session.stop(&client)?;
239244
#[cfg(feature = "bonsai-auto-scaling")]
240245
auto_scaling::shutdown_bonsai().await?;
@@ -257,7 +262,7 @@ pub async fn prove_bonsai<O: Eq + Debug + DeserializeOwned>(
257262
// Prepare input data
258263
let input_data = bytemuck::cast_slice(&encoded_input).to_vec();
259264

260-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
265+
let client = Client::from_env(risc0_zkvm::VERSION)?;
261266
client.upload_img(&encoded_image_id, elf.to_vec())?;
262267
// upload input
263268
let input_id = client.upload_input(input_data.clone())?;
@@ -266,6 +271,7 @@ pub async fn prove_bonsai<O: Eq + Debug + DeserializeOwned>(
266271
encoded_image_id.clone(),
267272
input_id.clone(),
268273
assumption_uuids.clone(),
274+
false,
269275
)?;
270276

271277
if let Some(id_store) = id_store {
@@ -277,7 +283,13 @@ pub async fn prove_bonsai<O: Eq + Debug + DeserializeOwned>(
277283
})?;
278284
}
279285

280-
verify_bonsai_receipt(image_id, expected_output, session.uuid.clone(), 8).await
286+
verify_bonsai_receipt(
287+
image_id,
288+
expected_output,
289+
session.uuid.clone(),
290+
MAX_REQUEST_RETRY,
291+
)
292+
.await
281293
}
282294

283295
pub async fn bonsai_stark_to_snark(
@@ -286,10 +298,14 @@ pub async fn bonsai_stark_to_snark(
286298
input: B256,
287299
) -> ProverResult<Risc0Response> {
288300
let image_id = Digest::from(RISC0_GUEST_ID);
289-
let (snark_uuid, snark_receipt) =
290-
stark2snark(image_id, stark_uuid.clone(), stark_receipt.clone())
291-
.await
292-
.map_err(|err| format!("Failed to convert STARK to SNARK: {err:?}"))?;
301+
let (snark_uuid, snark_receipt) = stark2snark(
302+
image_id,
303+
stark_uuid.clone(),
304+
stark_receipt.clone(),
305+
MAX_REQUEST_RETRY,
306+
)
307+
.await
308+
.map_err(|err| format!("Failed to convert STARK to SNARK: {err:?}"))?;
293309

294310
info!("Validating SNARK uuid: {snark_uuid}");
295311

@@ -382,8 +398,10 @@ pub fn load_receipt<T: serde::de::DeserializeOwned>(
382398

383399
pub fn save_receipt<T: serde::Serialize>(receipt_label: &String, receipt_data: &(String, T)) {
384400
if !is_dev_mode() {
401+
let cache_path = zkp_cache_path(receipt_label);
402+
info!("Saving receipt to cache: {cache_path:?}");
385403
fs::write(
386-
zkp_cache_path(receipt_label),
404+
cache_path,
387405
bincode::serialize(receipt_data).expect("Failed to serialize receipt!"),
388406
)
389407
.expect("Failed to save receipt output file.");
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub const RISC0_AGGREGATION_ELF: &[u8] =
22
include_bytes!("../../../guest/target/riscv32im-risc0-zkvm-elf/release/risc0-aggregation");
33
pub const RISC0_AGGREGATION_ID: [u32; 8] = [
4-
3593026424, 359928015, 3488866833, 2676323972, 1129344711, 55769507, 233041442, 3293280986,
4+
3190692238, 1991537256, 2457220677, 1764592515, 1585399420, 97928005, 276688816, 447831862,
55
];
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub const RISC0_GUEST_ELF: &[u8] =
22
include_bytes!("../../../guest/target/riscv32im-risc0-zkvm-elf/release/risc0-guest");
33
pub const RISC0_GUEST_ID: [u32; 8] = [
4-
2522428380, 1790994278, 397707036, 244564411, 3780865207, 1282154214, 1673205005, 3172292887,
4+
3473581204, 2561439051, 2320161003, 3018340632, 1481329104, 1608433297, 3314099706, 2669934765,
55
];

provers/risc0/driver/src/snarks.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::{str::FromStr, sync::Arc};
1717
use alloy_primitives::B256;
1818
use alloy_sol_types::{sol, SolValue};
1919
use anyhow::Result;
20-
use bonsai_sdk::alpha::responses::SnarkReceipt;
20+
use bonsai_sdk::blocking::Client;
2121
use ethers_contract::abigen;
2222
use ethers_core::types::H160;
2323
use ethers_providers::{Http, Provider, RetryClient};
@@ -27,6 +27,7 @@ use risc0_zkvm::{
2727
sha::{Digest, Digestible},
2828
Groth16ReceiptVerifierParameters, Receipt,
2929
};
30+
use tokio::time::{sleep as tokio_async_sleep, Duration};
3031

3132
use tracing::{error as tracing_err, info as tracing_info};
3233

@@ -86,7 +87,8 @@ pub async fn stark2snark(
8687
image_id: Digest,
8788
stark_uuid: String,
8889
stark_receipt: Receipt,
89-
) -> Result<(String, SnarkReceipt)> {
90+
max_retries: usize,
91+
) -> Result<(String, Receipt)> {
9092
info!("Submitting SNARK workload");
9193
// Label snark output as journal digest
9294
let receipt_label = format!(
@@ -106,20 +108,38 @@ pub async fn stark2snark(
106108
stark_uuid
107109
};
108110

109-
let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?;
110-
let snark_uuid = client.create_snark(stark_uuid)?;
111+
let client = Client::from_env(risc0_zkvm::VERSION)?;
112+
let snark_uuid = client.create_snark(stark_uuid.clone())?;
111113

114+
let mut retry = 0;
112115
let snark_receipt = loop {
113116
let res = snark_uuid.status(&client)?;
114-
115117
if res.status == "RUNNING" {
116-
info!("Current status: {} - continue polling...", res.status);
117-
std::thread::sleep(std::time::Duration::from_secs(15));
118+
info!(
119+
"Current {:?} status: {} - continue polling...",
120+
&stark_uuid, res.status
121+
);
122+
tokio_async_sleep(Duration::from_secs(15)).await;
118123
} else if res.status == "SUCCEEDED" {
119-
break res
124+
let download_url = res
120125
.output
121126
.expect("Bonsai response is missing SnarkReceipt.");
127+
let receipt_buf = client.download(&download_url)?;
128+
let snark_receipt: Receipt = bincode::deserialize(&receipt_buf)?;
129+
break snark_receipt;
122130
} else {
131+
if retry < max_retries {
132+
retry += 1;
133+
info!(
134+
"Workflow {:?} exited: {} - | err: {} - retrying {}/{max_retries}",
135+
stark_uuid,
136+
res.status,
137+
res.error_msg.unwrap_or_default(),
138+
retry
139+
);
140+
tokio_async_sleep(Duration::from_secs(15)).await;
141+
continue;
142+
}
123143
panic!(
124144
"Workflow exited: {} - | err: {}",
125145
res.status,
@@ -129,15 +149,15 @@ pub async fn stark2snark(
129149
};
130150

131151
let stark_psd = stark_receipt.claim()?.as_value().unwrap().post.digest();
132-
let snark_psd = Digest::try_from(snark_receipt.post_state_digest.as_slice())?;
152+
let snark_psd = snark_receipt.claim()?.as_value().unwrap().post.digest();
133153

134154
if stark_psd != snark_psd {
135155
error!("SNARK/STARK Post State Digest mismatch!");
136156
error!("STARK: {}", hex::encode(stark_psd));
137157
error!("SNARK: {}", hex::encode(snark_psd));
138158
}
139159

140-
if snark_receipt.journal != stark_receipt.journal.bytes {
160+
if snark_receipt.journal.bytes != stark_receipt.journal.bytes {
141161
error!("SNARK/STARK Receipt Journal mismatch!");
142162
error!("STARK: {}", hex::encode(&stark_receipt.journal.bytes));
143163
error!("SNARK: {}", hex::encode(&snark_receipt.journal));
@@ -152,11 +172,12 @@ pub async fn stark2snark(
152172

153173
pub async fn verify_groth16_from_snark_receipt(
154174
image_id: Digest,
155-
snark_receipt: SnarkReceipt,
175+
snark_receipt: Receipt,
156176
) -> Result<Vec<u8>> {
157-
let seal = encode(snark_receipt.snark.to_vec())?;
177+
let groth16_claim = snark_receipt.inner.groth16().unwrap();
178+
let seal = groth16_claim.seal.clone();
158179
let journal_digest = snark_receipt.journal.digest();
159-
let post_state_digest = snark_receipt.post_state_digest.digest();
180+
let post_state_digest = snark_receipt.claim()?.as_value().unwrap().post.digest();
160181
let encoded_proof =
161182
verify_groth16_snark_impl(image_id, seal, journal_digest, post_state_digest).await?;
162183
let proof = (encoded_proof, B256::from_slice(image_id.as_bytes()))

0 commit comments

Comments
 (0)