Skip to content

Commit

Permalink
Merge pull request #23 from zksecurity/support-both-stone-v5-and-v6
Browse files Browse the repository at this point in the history
Support both stone v5 and v6 binaries
  • Loading branch information
mellowcroc authored Oct 30, 2024
2 parents 5cff0c3 + 1fb307d commit 00e2eef
Show file tree
Hide file tree
Showing 13 changed files with 18,793 additions and 2,694 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ serde = { version = "1.0", features = ["derive"], default-features = false }
serde_json = "1"
sha256 = "1.5.0"
tar = "0.4.41"
tempfile = "3.10.1"
thiserror = "1.0.61"

[dev-dependencies]
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Additional args:
- `--prover_config_file`
- `--parameter_file`
- `--output`
- `--stone_version`: [v5](https://github.com/starkware-libs/stone-prover/commit/7ac17c8ba63a789604350e501558ef0ab990fd88) and [v6](https://github.com/starkware-libs/stone-prover/commit/1414a545e4fb38a85391289abe91dd4467d268e1) are not compatible because v6 additionally [includes the `n_verifier_friendly_commitment_layers` value](https://github.com/starkware-libs/stone-prover/commit/1414a545e4fb38a85391289abe91dd4467d268e1#diff-ed7255be97fbeb539a95132b4f2dea9753b8a40f9f59ea220f3c2eeb3afd1fc1R94) when calculating the public input hash.

Additional args for prover parameters. Most of them are related to optimizations or the security level of the proof. You can refer to the [RFC](https://zksecurity.github.io/RFCs/) for more details on some of them.

Expand Down Expand Up @@ -119,15 +120,15 @@ Additional args:

![Proving and verifying on Ethereum](./assets/stone-cli-workflow2.svg)

Currently there is a Solidity verifier deployed on Ethereum, which is mainly used to verify SHARP proofs created by L2 Starknet nodes. The Solidity verifier checks the validity of a Cairo program named `bootloader`, which can prove the execution of multiple Cairo programs or Cairo PIEs (Position Independent Executable) either by executing them directly in the program or by running a Cairo verifier that recursively verifies (i.e. verify a proof inside the program) a bootloader proof. The bootloader program dramatically lowers the cost of verification as proving a new Cairo program will grow the size of the proof logarithmically as opposed to linearly. Once we create a bootloader proof, we need to serialize it to a format that works for the Cairo verifier on Ethereum. (Note: Recursive verification is not supported yet)
Currently there is a Solidity verifier deployed on Ethereum, which is mainly used to verify SHARP proofs created by L2 Starknet nodes. The Solidity verifier checks the validity of a Cairo program named `bootloader`, which can prove the execution of multiple Cairo programs or Cairo PIEs (Position Independent Executable) either by executing them directly in the program or by running a Cairo verifier that recursively verifies (i.e. verify a proof inside the program) a bootloader proof. The bootloader program dramatically lowers the cost of verification as proving a new Cairo program will grow the size of the proof logarithmically as opposed to linearly. Once we create a bootloader proof, we need to serialize it to a format that works for the Cairo verifier on Ethereum. (Note: the Solidity verifier is based on Stone version `v5`, so the `--stone_version` argument needs to be set to `v5`)

Here are the specific steps for the above process:

1. Call `stone-cli prove-bootloader --cairo_programs ./examples/cairo0/bitwise_output.json --layout starknet --parameter_file ./tests/configs/bootloader_cpu_air_params.json --output bootloader_proof.json --fact_topologies_output fact_topologies.json`

- Can also provide multiple programs and pies by providing a space-separated list of paths

2. Call `stone-cli verify --proof bootloader_proof.json --annotation_file annotation.json --extra_output_file extra_output.json`
2. Call `stone-cli verify --proof bootloader_proof.json --annotation_file annotation.json --extra_output_file extra_output.json --stone_version v5`

3. Call `stone-cli serialize-proof --proof bootloader_proof.json --annotation_file annotation.json --extra_output_file extra_output.json --network ethereum --output bootloader_serialized_proof.json`

Expand All @@ -153,6 +154,11 @@ Here are the specific steps for the above process:

Before running the tests, make sure to increase the Rust default stack size via `export RUST_MIN_STACK=4194304`. After that, you can run `cargo test` to run all the tests.

## Versioning guide

- Minor version changes should be made when the underlying `cairo1-run` binary built from [cairo-vm](https://github.com/lambdaclass/cairo-vm) is updated.
- When updating the `cairo1-run` binary, the `cairo` release version specified in `build.rs` should also be updated to a compatible version.

## Additional Resources

### List of supported builtins per layout
Expand Down
345 changes: 203 additions & 142 deletions build.rs

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions configs/env.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{
"download_dir": ".stone-cli/v0.1.0",
"file_names": [
"cairo1-run",
"cpu_air_prover",
"cpu_air_verifier"
"cairo1-run-v2.0.0-rc0",
"cpu_air_prover_v5",
"cpu_air_verifier_v5",
"cpu_air_prover_v6",
"cpu_air_verifier_v6"
],
"env_names": [
"CAIRO1_RUN",
"CPU_AIR_PROVER",
"CPU_AIR_VERIFIER"
"CPU_AIR_PROVER_V5",
"CPU_AIR_VERIFIER_V5",
"CPU_AIR_PROVER_V6",
"CPU_AIR_VERIFIER_V6"
]
}
12 changes: 12 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ pub struct ProveArgs {

#[clap(flatten)]
pub prover_config: ProverConfig,

#[clap(long = "stone_version", default_value = "v6", value_enum)]
pub stone_version: StoneVersion,
}

#[derive(Args, Debug)]
Expand Down Expand Up @@ -99,6 +102,9 @@ pub struct VerifyArgs {

#[clap(long = "extra_output_file", value_hint=ValueHint::FilePath, help = "Path to the output file that will contain additional interaction elements necessary for generating split proofs")]
pub extra_output_file: Option<PathBuf>,

#[clap(long = "stone_version", default_value = "v6", value_enum)]
pub stone_version: StoneVersion,
}

define_enum! {
Expand Down Expand Up @@ -173,6 +179,12 @@ impl LayoutName {
}
}

define_enum! {
StoneVersion,
V5 => "V5",
V6 => "V6",
}

#[derive(Args, Debug, Clone)]
pub struct SerializeArgs {
#[clap(long = "proof", value_hint=ValueHint::FilePath)]
Expand Down
46 changes: 42 additions & 4 deletions src/prover.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
pub mod config;

use crate::args::{ProveArgs, ProveBootloaderArgs};
use crate::args::{ProveArgs, ProveBootloaderArgs, StoneVersion};
use crate::utils::write_json_to_file;
use config::{ProverConfig, ProverParametersConfig};
use std::fs;
use std::path::PathBuf;
use std::process::Command;
use stone_prover_sdk::error::ProverError;
use thiserror::Error;

use stone_prover_sdk::models::PublicInput;

#[derive(Error, Debug)]
pub enum ProverError {
#[error("{0}")]
IoError(#[from] std::io::Error),
#[error("{0}")]
CommandError(ProverCommandError),
}

#[derive(Debug)]
pub struct ProverCommandError {
output: std::process::Output,
stone_version: StoneVersion,
}

impl std::fmt::Display for ProverCommandError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"failed to run stone prover with version: {:?}, status: {}, stderr: {}",
self.stone_version,
self.output.status,
String::from_utf8(self.output.stderr.clone()).unwrap()
)
}
}

/// Runs the Stone prover with the given inputs
///
/// # Arguments
Expand All @@ -34,6 +61,7 @@ pub fn run_stone_prover(
&prove_args.prover_config,
prove_args.prover_config_file.as_ref(),
&prove_args.output,
&prove_args.stone_version,
air_public_input,
air_private_input,
tmp_dir,
Expand Down Expand Up @@ -69,6 +97,7 @@ pub fn run_stone_prover_bootloader(
&prove_bootloader_args.prover_config,
prove_bootloader_args.prover_config_file.as_ref(),
&prove_bootloader_args.output,
&StoneVersion::V5,
air_public_input,
air_private_input,
tmp_dir,
Expand All @@ -85,6 +114,7 @@ fn run_stone_prover_internal(
prover_config: &ProverConfig,
prover_config_file: Option<&PathBuf>,
output_file: &PathBuf,
stone_version: &StoneVersion,
air_public_input: &PathBuf,
air_private_input: &PathBuf,
tmp_dir: &tempfile::TempDir,
Expand Down Expand Up @@ -119,6 +149,7 @@ fn run_stone_prover_internal(
prover_parameters_path,
output_file,
true,
stone_version,
)?;

Ok(())
Expand All @@ -131,9 +162,13 @@ fn run_prover_from_command_line_with_annotations(
prover_parameter_file: &PathBuf,
output_file: &PathBuf,
generate_annotations: bool,
stone_version: &StoneVersion,
) -> Result<(), ProverError> {
// TODO: Add better error handling
let prover_run_path = std::env::var("CPU_AIR_PROVER").unwrap();
let prover_run_path = match stone_version {
StoneVersion::V5 => std::env::var("CPU_AIR_PROVER_V5").unwrap(),
StoneVersion::V6 => std::env::var("CPU_AIR_PROVER_V6").unwrap(),
};

let mut command = Command::new(prover_run_path);
command
Expand All @@ -153,7 +188,10 @@ fn run_prover_from_command_line_with_annotations(

let output = command.output()?;
if !output.status.success() {
return Err(ProverError::CommandError(output));
return Err(ProverError::CommandError(ProverCommandError {
output,
stone_version: stone_version.clone(),
}));
}

Ok(())
Expand Down
4 changes: 3 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ pub fn parse(config: &str) -> Config {
}

pub fn set_env_vars(config: &Config) {
let download_dir = Path::new(env!("HOME")).join(&config.download_dir);
let download_dir = Path::new(env!("HOME"))
.join(&config.download_dir)
.join("executables");
for (env_name, filename) in config.env_names.iter().zip(config.file_names.iter()) {
let full_path = download_dir.join(filename);
unsafe {
Expand Down
48 changes: 43 additions & 5 deletions src/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,43 @@
use std::path::PathBuf;
use stone_prover_sdk::error::VerifierError;
use thiserror::Error;

use crate::args::VerifyArgs;
use crate::args::{StoneVersion, VerifyArgs};

#[derive(Error, Debug)]
pub enum VerifierError {
#[error("{0}")]
IoError(#[from] std::io::Error),
#[error("{0}")]
CommandError(VerifierCommandError),
}

#[derive(Debug)]
pub struct VerifierCommandError {
output: std::process::Output,
stone_version: StoneVersion,
}

impl std::fmt::Display for VerifierCommandError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"failed to run stone verifier with version: {:?}, status: {}, stderr: {}",
self.stone_version,
self.output.status,
String::from_utf8(self.output.stderr.clone()).unwrap()
)
}
}

pub fn run_stone_verifier(args: VerifyArgs) -> Result<(), VerifierError> {
println!("Running stone verifier...");

run_verifier_from_command_line(&args.proof, args.annotation_file, args.extra_output_file)?;
run_verifier_from_command_line(
&args.proof,
args.annotation_file,
args.extra_output_file,
&args.stone_version,
)?;

println!("Verification successful!");
Ok(())
Expand All @@ -16,8 +47,12 @@ fn run_verifier_from_command_line(
in_file: &PathBuf,
annotation_file: Option<PathBuf>,
extra_output_file: Option<PathBuf>,
stone_version: &StoneVersion,
) -> Result<(), VerifierError> {
let verifier_run_path = std::env::var("CPU_AIR_VERIFIER").unwrap();
let verifier_run_path = match stone_version {
StoneVersion::V5 => std::env::var("CPU_AIR_VERIFIER_V5").unwrap(),
StoneVersion::V6 => std::env::var("CPU_AIR_VERIFIER_V6").unwrap(),
};

let mut command = std::process::Command::new(verifier_run_path);
command.arg("--in_file").arg(in_file);
Expand All @@ -33,7 +68,10 @@ fn run_verifier_from_command_line(
let output = command.output()?;

if !output.status.success() {
return Err(VerifierError::CommandError(output));
return Err(VerifierError::CommandError(VerifierCommandError {
output,
stone_version: stone_version.clone(),
}));
}

Ok(())
Expand Down
Loading

0 comments on commit 00e2eef

Please sign in to comment.