Skip to content

Commit 015420b

Browse files
take output from runner instead of from proof (#207)
## Type - [ ] feature - [ ] bugfix - [ ] dev (no functional changes, no API changes) - [ ] fmt (formatting, renaming) - [ ] build - [ ] docs - [ ] testing ## Description ## Breaking changes? - [ ] yes - [ ] no <!-- Reviewable:start --> - - - This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/starkware-libs/bootloader-hints/207) <!-- Reviewable:end -->
1 parent 520dc13 commit 015420b

File tree

1 file changed

+37
-32
lines changed
  • crates/stwo_run_and_prove/src

1 file changed

+37
-32
lines changed

crates/stwo_run_and_prove/src/main.rs

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ use cairo_air::utils::ProofFormat;
22
use cairo_air::verifier::verify_cairo;
33
use cairo_program_runner_lib::cairo_run_program;
44
use cairo_program_runner_lib::utils::{get_cairo_run_config, get_program, get_program_input};
5+
use cairo_vm::Felt252;
56
use cairo_vm::types::errors::program_errors::ProgramError;
67
use cairo_vm::types::layout_name::LayoutName;
78
use cairo_vm::vm::errors::cairo_run_errors::CairoRunError;
89
use cairo_vm::vm::errors::runner_errors::RunnerError;
10+
use cairo_vm::vm::errors::vm_errors::VirtualMachineError;
11+
use cairo_vm::vm::runners::cairo_runner::CairoRunner;
912
use clap::Parser;
1013
#[cfg(test)]
1114
use mockall::automock;
@@ -32,8 +35,6 @@ use stwo_cairo_utils::file_utils::{IoErrorWithPath, create_file, read_to_string}
3235
use thiserror::Error;
3336
use tracing::{error, info, warn};
3437

35-
type OutputVec = Vec<[u32; 8]>;
36-
3738
fn parse_usize_ge1(s: &str) -> Result<usize, String> {
3839
let v: usize = s.parse().map_err(|_| "must be a number".to_string())?;
3940
if v >= 1 {
@@ -119,8 +120,12 @@ enum StwoRunAndProveError {
119120
Serializing(#[from] sonic_rs::error::Error),
120121
#[error(transparent)]
121122
Proving(#[from] ProvingError),
123+
#[error(transparent)]
124+
VM(#[from] VirtualMachineError),
122125
#[error("cairo verification failed.")]
123126
Verification,
127+
#[error("Failed to parse output line as Felt decimal.")]
128+
OutputParsing,
124129
}
125130

126131
// Implement From<Box<CairoRunError>> manually
@@ -193,11 +198,9 @@ fn stwo_run_and_prove(
193198
let runner = cairo_run_program(&program, program_input, cairo_run_config)?;
194199
info!("Adapting prover input.");
195200
let prover_input = adapter(&runner);
196-
let (successful_proof_attempt, output_vec) =
197-
prove_with_retries(prover_input, prove_config, prover)?;
198-
201+
let successful_proof_attempt = prove_with_retries(prover_input, prove_config, prover)?;
199202
if let Some(output_path) = program_output {
200-
save_output_to_file(output_vec, output_path)?;
203+
write_output_to_file(runner, output_path)?;
201204
}
202205

203206
Ok(successful_proof_attempt)
@@ -211,7 +214,7 @@ fn prove_with_retries(
211214
prover_input: ProverInput,
212215
prove_config: ProveConfig,
213216
prover: Box<dyn ProverTrait>,
214-
) -> Result<(usize, OutputVec), StwoRunAndProveError> {
217+
) -> Result<usize, StwoRunAndProveError> {
215218
let prover_params = match prove_config.prover_params_json {
216219
Some(ref path) => sonic_rs::from_str(&read_to_string(path)?)?,
217220
None => default_prod_prover_parameters(),
@@ -235,12 +238,12 @@ fn prove_with_retries(
235238
&proof_format,
236239
prove_config.verify,
237240
) {
238-
Ok(output_values) => {
241+
Ok(()) => {
239242
info!(
240243
"Proof generated and verified successfully on attempt {}/{}",
241244
i, prove_config.n_proof_attempts
242245
);
243-
return Ok((i, output_values));
246+
return Ok(i);
244247
}
245248

246249
Err(StwoRunAndProveError::Verification) => {
@@ -272,7 +275,7 @@ fn choose_channel_and_prove(
272275
proof_file_path: PathBuf,
273276
proof_format: &ProofFormat,
274277
verify: bool,
275-
) -> Result<OutputVec, StwoRunAndProveError> {
278+
) -> Result<(), StwoRunAndProveError> {
276279
match prover_params.channel_hash {
277280
ChannelHash::Blake2s => prove::<Blake2sMerkleChannel>(
278281
prover_params,
@@ -300,7 +303,7 @@ trait ProverTrait {
300303
proof_file_path: PathBuf,
301304
proof_format: &ProofFormat,
302305
verify: bool,
303-
) -> Result<OutputVec, StwoRunAndProveError>;
306+
) -> Result<(), StwoRunAndProveError>;
304307
}
305308

306309
struct StwoProverEntryPoint;
@@ -313,7 +316,7 @@ impl ProverTrait for StwoProverEntryPoint {
313316
proof_file_path: PathBuf,
314317
proof_format: &ProofFormat,
315318
verify: bool,
316-
) -> Result<OutputVec, StwoRunAndProveError> {
319+
) -> Result<(), StwoRunAndProveError> {
317320
choose_channel_and_prove(
318321
prover_params,
319322
prover_input,
@@ -334,7 +337,7 @@ fn prove<MC: MerkleChannel>(
334337
proof_file_path: PathBuf,
335338
proof_format: &ProofFormat,
336339
verify: bool,
337-
) -> Result<OutputVec, StwoRunAndProveError>
340+
) -> Result<(), StwoRunAndProveError>
338341
where
339342
SimdBackend: BackendForChannel<MC>,
340343
MC::H: Serialize,
@@ -361,8 +364,6 @@ where
361364
}
362365
}
363366

364-
let output_addresses_and_values = proof.claim.public_data.public_memory.output.clone();
365-
366367
if verify {
367368
// We want to map this error to `StwoRunAndProveError::Verification` because we intend to
368369
// retry the proof generation in case of a verification failure. In the calling function we
@@ -372,23 +373,27 @@ where
372373
.map_err(|_| StwoRunAndProveError::Verification)?;
373374
}
374375

375-
let output_values = output_addresses_and_values
376-
.into_iter()
377-
.map(|(_, value)| value)
378-
.collect();
379-
380-
Ok(output_values)
376+
Ok(())
381377
}
382378

383-
/// Saves the program output to the specified output path as [u32; 8] values,
384-
/// that will be converted to [u256] in the Prover service.
385-
fn save_output_to_file(
386-
output_vec: OutputVec,
379+
/// Write the program output to the specified output path as Felt252 values.
380+
fn write_output_to_file(
381+
mut runner: CairoRunner,
387382
output_path: PathBuf,
388383
) -> Result<(), StwoRunAndProveError> {
389384
info!("Saving program output to: {:?}", output_path);
390-
let serialized_output = sonic_rs::to_string(&output_vec)?;
391-
std::fs::write(output_path, serialized_output)?;
385+
// TODO(Nitsan): move this function to cairo_program_runner_lib or a new utils lib,
386+
// and call it from here and from cairo_program_runner.
387+
388+
let mut output_buffer = String::new();
389+
runner.vm.write_output(&mut output_buffer)?;
390+
let output_lines = output_buffer
391+
.lines()
392+
.map(|line: &str| {
393+
Felt252::from_dec_str(line).map_err(|_| StwoRunAndProveError::OutputParsing)
394+
})
395+
.collect::<Result<Vec<Felt252>, _>>()?;
396+
std::fs::write(output_path, sonic_rs::to_string_pretty(&output_lines)?)?;
392397
Ok(())
393398
}
394399

@@ -399,7 +404,7 @@ mod tests {
399404
use std::fs;
400405
use tempfile::{NamedTempFile, TempDir, TempPath};
401406

402-
const ARRAY_SUM_EXPECTED_OUTPUT: [u32; 8] = [50, 0, 0, 0, 0, 0, 0, 0];
407+
const ARRAY_SUM_EXPECTED_OUTPUT: [Felt252; 1] = [Felt252::from_hex_unchecked("0x32")];
403408
const RESOURCES_PATH: &str = "resources";
404409
const PROGRAM_FILE_NAME: &str = "array_sum.json";
405410
const PROVER_PARAMS_FILE_NAME: &str = "prover_params.json";
@@ -466,7 +471,7 @@ mod tests {
466471
.returning(move |_, _, proof_file, _, _| {
467472
let expected_proof_file = get_path(EXPECTED_PROOF_FILE_NAME);
468473
fs::copy(&expected_proof_file, &proof_file).expect("Failed to copy proof file.");
469-
Ok(vec![ARRAY_SUM_EXPECTED_OUTPUT])
474+
Ok(())
470475
});
471476

472477
let successful_proof_attempt =
@@ -512,7 +517,7 @@ mod tests {
512517
// for the last attempt.
513518
let mut results = (0..n_proof_attempts.saturating_sub(1))
514519
.map(|_| Err(StwoRunAndProveError::Verification))
515-
.chain(std::iter::once(Ok(vec![ARRAY_SUM_EXPECTED_OUTPUT])));
520+
.chain(std::iter::once(Ok(())));
516521

517522
mock_prover
518523
.expect_choose_channel_and_prove()
@@ -556,10 +561,10 @@ mod tests {
556561
// Verifying the proof output.
557562
let output_content =
558563
std::fs::read_to_string(output_temp_file).expect("Failed to read output file");
559-
let output_vec: OutputVec =
564+
let output: Vec<Felt252> =
560565
sonic_rs::from_str(&output_content).expect("Failed to parse output");
561566
assert_eq!(
562-
output_vec[0], ARRAY_SUM_EXPECTED_OUTPUT,
567+
output, ARRAY_SUM_EXPECTED_OUTPUT,
563568
"Expected output to be {:?}",
564569
ARRAY_SUM_EXPECTED_OUTPUT
565570
);

0 commit comments

Comments
 (0)