Skip to content

Commit d1eb0f1

Browse files
authored
Merge pull request #127 from HerodotusDev/better_cairo_runners
5 - better cairo-vm runners
2 parents f0a87ae + 504523a commit d1eb0f1

File tree

15 files changed

+205
-137
lines changed

15 files changed

+205
-137
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
RPC_URL_ETHEREUM=
2+
RPC_URL_FEEDER_GATEWAY=https://alpha-sepolia.starknet.io/feeder_gateway/
3+
RPC_URL_HERODOTUS_INDEXER=https://grower-indexer.api.herodotus.cloud/accumulators/proofs/
4+
RPC_URL_STARKNET=

Cargo.lock

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

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ source venv/bin/activate
1818

1919
## Running
2020

21-
Before running the program, prepare the input data. The inputs are provided via the `hdp_input.json` file located in the root directory of the HDP project.
21+
Before running the program, prepare the input data. The inputs are provided via the [hdp_input.json](examples/hdp_input.json).
22+
Runtime require chain nodes RPC calls, ensure an environment variables [.env.example](.env.example) are set.
2223

2324
### Steps to Execute:
2425

@@ -34,7 +35,7 @@ Before running the program, prepare the input data. The inputs are provided via
3435

3536
3. **Run Cairo1 Module with Verified On-Chain Data:**
3637
```bash
37-
cargo run --release --bin sound_run -- --program_input examples/hdp_input.json --program_proofs hdp_proofs.json --program_output hdp_output.json --layout starknet_with_keccak
38+
cargo run --release --bin sound_run -- --program_input examples/hdp_input.json --program_proofs hdp_proofs.json --print_output --layout starknet_with_keccak --cairo_pie_output pie.zip
3839
```
3940

4041
The program will output the results root and tasks root. These roots can be used to extract the results from the on-chain contract.
@@ -60,7 +61,7 @@ The overall program is split into two main parts:
6061

6162
## Testing
6263

63-
Some tests require chain nodes RPC calls. Ensure an environment variable named `ETH_RPC` and `STARKNET_RPC` is set.
64+
Tests require chain nodes RPC calls. Ensure an environment variables [.env.example](.env.example) are set.
6465

6566
1. **Build Cairo1 Modules:**
6667
```bash

crates/dry_hint_processor/src/syscall_handler/evm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl SyscallHandler for CallContractHandler {
5353
.map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?,
5454
));
5555

56-
let retdata_start = vm.add_temporary_segment();
56+
let retdata_start = vm.add_memory_segment();
5757
let mut retdata_end = retdata_start;
5858

5959
match call_handler_id {

crates/dry_hint_processor/src/syscall_handler/starknet/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl SyscallHandler for CallContractHandler {
4747
.map_err(|e| SyscallExecutionError::InternalError(format!("{}", e).into()))?,
4848
));
4949

50-
let retdata_start = vm.add_temporary_segment();
50+
let retdata_start = vm.add_memory_segment();
5151
let mut retdata_end = retdata_start;
5252

5353
match call_handler_id {

crates/dry_run/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ clap.workspace = true
99
dry_hint_processor.workspace = true
1010
hints.workspace = true
1111
serde_json.workspace = true
12-
thiserror.workspace = true
1312
tokio.workspace = true
1413
tracing-subscriber.workspace = true
1514
tracing.workspace = true

crates/dry_run/src/main.rs

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@
44
#![forbid(unsafe_code)]
55

66
use cairo_vm::{
7-
cairo_run::CairoRunConfig,
8-
types::{layout_name::LayoutName, program::Program},
9-
vm::{
10-
errors::vm_exception::VmException,
11-
runners::cairo_runner::{CairoRunner, RunnerMode},
12-
},
7+
cairo_run::{self, cairo_run_program},
8+
types::{layout::CairoLayoutParams, layout_name::LayoutName, program::Program},
139
};
1410
use clap::Parser;
1511
use dry_hint_processor::{
@@ -19,70 +15,101 @@ use dry_hint_processor::{
1915
use hints::vars;
2016
use std::{env, path::PathBuf};
2117
use tracing::debug;
22-
use types::HDPDryRunInput;
18+
use types::{error::Error, HDPDryRunInput};
2319

2420
#[derive(Parser, Debug)]
2521
#[clap(author, version, about, long_about = None)]
2622
struct Args {
27-
#[clap(long = "layout", default_value = "plain", value_enum)]
28-
layout: LayoutName,
29-
#[structopt(long = "proof_mode")]
30-
proof_mode: bool,
3123
#[structopt(long = "program_input")]
3224
program_input: PathBuf,
3325
#[structopt(long = "program_output")]
3426
program_output: PathBuf,
27+
#[clap(long = "trace_file", value_parser)]
28+
trace_file: Option<PathBuf>,
29+
#[structopt(long = "print_output")]
30+
print_output: bool,
31+
#[structopt(long = "memory_file")]
32+
memory_file: Option<PathBuf>,
33+
/// When using dynamic layout, it's parameters must be specified through a layout params file.
34+
#[clap(long = "layout", default_value = "plain", value_enum)]
35+
layout: LayoutName,
36+
/// Required when using with dynamic layout.
37+
/// Ignored otherwise.
38+
#[clap(long = "cairo_layout_params_file", required_if_eq("layout", "dynamic"))]
39+
cairo_layout_params_file: Option<PathBuf>,
40+
#[structopt(long = "proof_mode")]
41+
proof_mode: bool,
42+
#[structopt(long = "secure_run")]
43+
secure_run: Option<bool>,
44+
#[clap(long = "air_public_input", requires = "proof_mode")]
45+
air_public_input: Option<PathBuf>,
46+
#[clap(
47+
long = "air_private_input",
48+
requires_all = ["proof_mode", "trace_file", "memory_file"]
49+
)]
50+
air_private_input: Option<PathBuf>,
51+
#[clap(
52+
long = "cairo_pie_output",
53+
// We need to add these air_private_input & air_public_input or else
54+
// passing cairo_pie_output + either of these without proof_mode will not fail
55+
conflicts_with_all = ["proof_mode", "air_private_input", "air_public_input"]
56+
)]
57+
cairo_pie_output: Option<PathBuf>,
58+
#[structopt(long = "allow_missing_builtins")]
59+
allow_missing_builtins: Option<bool>,
3560
}
3661

3762
#[tokio::main(flavor = "multi_thread", worker_threads = 1)]
38-
async fn main() -> Result<(), HdpOsError> {
63+
async fn main() -> Result<(), Error> {
3964
tracing_subscriber::fmt::init();
4065

41-
let args = Args::try_parse_from(std::env::args()).map_err(HdpOsError::Args)?;
66+
let args = Args::try_parse_from(std::env::args()).map_err(Error::Cli)?;
67+
68+
let cairo_layout_params = match args.cairo_layout_params_file {
69+
Some(file) => Some(CairoLayoutParams::from_file(&file)?),
70+
None => None,
71+
};
4272

4373
// Init CairoRunConfig
44-
let cairo_run_config = CairoRunConfig {
74+
let cairo_run_config = cairo_run::CairoRunConfig {
75+
trace_enabled: args.trace_file.is_some() || args.air_public_input.is_some(),
76+
relocate_mem: args.memory_file.is_some() || args.air_public_input.is_some(),
4577
layout: args.layout,
46-
relocate_mem: true,
47-
trace_enabled: true,
78+
proof_mode: args.proof_mode,
79+
secure_run: args.secure_run,
80+
allow_missing_builtins: args.allow_missing_builtins,
81+
dynamic_layout_params: cairo_layout_params,
4882
..Default::default()
4983
};
5084

5185
// Locate the compiled program file in the `OUT_DIR` folder.
5286
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR is not set"));
5387
let program_file_path = out_dir.join("cairo").join("compiled.json");
5488

55-
let program_file = std::fs::read(program_file_path).map_err(HdpOsError::IO)?;
56-
let program_inputs: HDPDryRunInput = serde_json::from_slice(&std::fs::read(args.program_input).map_err(HdpOsError::IO)?)?;
89+
let program_file = std::fs::read(program_file_path).map_err(Error::IO)?;
90+
let program_inputs: HDPDryRunInput = serde_json::from_slice(&std::fs::read(args.program_input).map_err(Error::IO)?)?;
5791

5892
// Load the Program
59-
let program = Program::from_bytes(&program_file, Some(cairo_run_config.entrypoint)).map_err(|e| HdpOsError::Runner(e.into()))?;
93+
let program = Program::from_bytes(&program_file, Some(cairo_run_config.entrypoint))?;
6094

61-
let runner_mode = if cairo_run_config.proof_mode {
62-
RunnerMode::ProofModeCairo1
63-
} else {
64-
RunnerMode::ExecutionMode
65-
};
66-
67-
// Init cairo runner
68-
let mut cairo_runner = CairoRunner::new_v2(&program, cairo_run_config.layout, None, runner_mode, cairo_run_config.trace_enabled)
69-
.map_err(|e| HdpOsError::Runner(e.into()))?;
70-
71-
// Init the Cairo VM
72-
let end = cairo_runner
73-
.initialize(cairo_run_config.allow_missing_builtins.unwrap_or(false))
74-
.map_err(|e| HdpOsError::Runner(e.into()))?;
75-
76-
// Run the Cairo VM
7795
let mut hint_processor = CustomHintProcessor::new(program_inputs);
78-
cairo_runner
79-
.run_until_pc(end, &mut hint_processor)
80-
.map_err(|err| VmException::from_vm_error(&cairo_runner, err))
81-
.map_err(|e| HdpOsError::Runner(e.into()))?;
96+
let mut cairo_runner = cairo_run_program(&program, &cairo_run_config, &mut hint_processor).unwrap();
8297

83-
cairo_runner.vm.compute_segments_effective_sizes();
8498
debug!("{:?}", cairo_runner.get_execution_resources());
8599

100+
if args.print_output {
101+
let mut output_buffer = "Program Output:\n".to_string();
102+
cairo_runner.vm.write_output(&mut output_buffer)?;
103+
print!("{output_buffer}");
104+
}
105+
106+
if let Some(ref file_name) = args.cairo_pie_output {
107+
cairo_runner
108+
.get_cairo_pie()
109+
.map_err(|e| Error::CairoPie(e.to_string()))?
110+
.write_zip_file(file_name)?
111+
}
112+
86113
std::fs::write(
87114
args.program_output,
88115
serde_json::to_vec::<SyscallHandler>(
@@ -94,26 +121,9 @@ async fn main() -> Result<(), HdpOsError> {
94121
.try_read()
95122
.unwrap(),
96123
)
97-
.map_err(|e| HdpOsError::IO(e.into()))?,
124+
.map_err(|e| Error::IO(e.into()))?,
98125
)
99-
.map_err(HdpOsError::IO)?;
126+
.map_err(Error::IO)?;
100127

101128
Ok(())
102129
}
103-
104-
use cairo_vm::vm::errors::cairo_run_errors::CairoRunError;
105-
use thiserror::Error;
106-
107-
#[derive(Error, Debug)]
108-
pub enum HdpOsError {
109-
#[error(transparent)]
110-
Args(#[from] clap::error::Error),
111-
#[error("Runner Error: {0}")]
112-
Runner(CairoRunError),
113-
#[error("Output Error: {0}")]
114-
Output(String),
115-
#[error(transparent)]
116-
IO(#[from] std::io::Error),
117-
#[error(transparent)]
118-
SerdeJson(#[from] serde_json::Error),
119-
}

crates/sound_hint_processor/src/syscall_handler/evm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl traits::SyscallHandler for CallContractHandler {
5757

5858
let memorizer = Memorizer::derive(vm, &mut calldata)?;
5959

60-
let retdata_start = vm.add_temporary_segment();
60+
let retdata_start = vm.add_memory_segment();
6161
let mut retdata_end = retdata_start;
6262

6363
match call_handler_id {

crates/sound_hint_processor/src/syscall_handler/starknet/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl traits::SyscallHandler for CallContractHandler {
5151

5252
let memorizer = Memorizer::derive(vm, &mut calldata)?;
5353

54-
let retdata_start = vm.add_temporary_segment();
54+
let retdata_start = vm.add_memory_segment();
5555
let mut retdata_end = retdata_start;
5656

5757
match call_handler_id {

crates/sound_run/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ cairo-vm.workspace = true
88
clap.workspace = true
99
serde_json.workspace = true
1010
sound_hint_processor.workspace = true
11-
thiserror.workspace = true
1211
tokio.workspace = true
1312
tracing-subscriber.workspace = true
1413
tracing.workspace = true

0 commit comments

Comments
 (0)