Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/dry_hint_processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ strum_macros.workspace = true
syscall_handler.workspace = true
tokio.workspace = true
tracing.workspace = true
types.workspace = true
types.workspace = true
serde_json.workspace = true
7 changes: 7 additions & 0 deletions crates/dry_hint_processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use crate::syscall_handler::{injected_state, unconstrained};

pub struct CustomHintProcessor {
inputs: HDPDryRunInput,
output_preimage_path: std::path::PathBuf,
builtin_hint_proc: BuiltinHintProcessor,
cairo1_builtin_hint_proc: Cairo1HintProcessor,
hints: HashMap<String, HintImpl>,
Expand All @@ -44,13 +45,18 @@ impl CustomHintProcessor {
pub fn new(inputs: HDPDryRunInput) -> Self {
Self {
inputs,
output_preimage_path: std::path::PathBuf::from("dry_run_output_preimage.json"),
builtin_hint_proc: BuiltinHintProcessor::new_empty(),
cairo1_builtin_hint_proc: Cairo1HintProcessor::new(Default::default(), Default::default(), true),
hints: Self::hints(),
extensive_hints: Self::extensive_hints(),
}
}

pub fn set_output_preimage_path(&mut self, path: std::path::PathBuf) {
self.output_preimage_path = path;
}

#[rustfmt::skip]
fn hints() -> HashMap<String, HintImpl> {
let mut hints = hints();
Expand Down Expand Up @@ -91,6 +97,7 @@ impl HintProcessorLogic for CustomHintProcessor {
let res = match hint_code {
crate::input::HINT_INPUT => self.hint_input(vm, exec_scopes, hpd, constants),
crate::output::HINT_OUTPUT => self.hint_output(vm, exec_scopes, hpd, constants),
crate::output::HINT_SAVE_OUTPUT_PREIMAGE => self.hint_save_output_preimage(vm, exec_scopes, hpd, constants),
_ => Err(HintError::UnknownHint(hint_code.to_string().into_boxed_str())),
};

Expand Down
61 changes: 58 additions & 3 deletions crates/dry_hint_processor/src/output.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
use std::collections::HashMap;

use cairo_vm::{
hint_processor::builtin_hint_processor::{
builtin_hint_processor_definition::HintProcessorData, hint_utils::get_relocatable_from_var_name,
hint_processor::{
builtin_hint_processor::{
builtin_hint_processor_definition::HintProcessorData,
hint_utils::{get_integer_from_var_name, get_relocatable_from_var_name},
},
hint_processor_utils::felt_to_usize,
},
types::exec_scope::ExecutionScopes,
types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use hints::vars;
use serde_json;

use super::CustomHintProcessor;

pub const HINT_OUTPUT: &str = "print(\"result\", [hex(ids.result.low), hex(ids.result.high)])";
pub const HINT_SAVE_OUTPUT_PREIMAGE: &str = "save_output_preimage(ids.retdata, ids.retdata_size)";

impl CustomHintProcessor {
pub fn hint_output(
Expand All @@ -33,4 +39,53 @@ impl CustomHintProcessor {
println!("result: {}, {}", result[0], result[1]);
Ok(())
}

pub fn hint_save_output_preimage(
&mut self,
vm: &mut VirtualMachine,
_exec_scopes: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let retdata_ptr = get_relocatable_from_var_name("retdata", vm, &hint_data.ids_data, &hint_data.ap_tracking)?;
let retdata_size = get_integer_from_var_name("retdata_size", vm, &hint_data.ids_data, &hint_data.ap_tracking)?;
let len = felt_to_usize(&retdata_size)?;

let cells = vm.get_continuous_range(retdata_ptr, len)?;

let mut values: Vec<Felt252> = Vec::new();
if len > 0 {
// Relocatable pointer at retdata[0]
let ptr = match &cells[0] {
MaybeRelocatable::RelocatableValue(ptr) => *ptr,
_ => {
return Err(HintError::CustomHint(
"Expected relocatable pointer at retdata[0]".to_owned().into_boxed_str(),
));
}
};
let slice = vm.get_continuous_range(ptr, len).map_err(HintError::Memory)?;
for el in slice.into_iter() {
match el {
MaybeRelocatable::Int(f) => values.push(f),
MaybeRelocatable::RelocatableValue(_) => {
return Err(HintError::CustomHint(
"Unexpected relocatable inside output array".to_owned().into_boxed_str(),
));
}
}
}
}

// Write directly to file using the path stored in the hint processor
let json_bytes = serde_json::to_vec(&values)
.map_err(|e| HintError::CustomHint(format!("Failed to serialize output preimage: {}", e).into_boxed_str()))?;
std::fs::write(&self.output_preimage_path, json_bytes).map_err(|e| {
HintError::CustomHint(
format!("Failed to write output preimage to {}: {}", self.output_preimage_path.display(), e).into_boxed_str(),
)
})?;

Ok(())
}
}
27 changes: 25 additions & 2 deletions crates/dry_run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use syscall_handler::{SyscallHandler, SyscallHandlerWrapper};
use tokio as _;
use tracing::{debug, info};
use tracing_subscriber as _;
use types::{error::Error, param::Param, CasmContractClass, HDPDryRunInput, HDPDryRunOutput, InjectedState};
use types::{error::Error, output_preimage, param::Param, CasmContractClass, HDPDryRunInput, HDPDryRunOutput, InjectedState};

pub const DRY_RUN_COMPILED_JSON: &str = env!("DRY_RUN_COMPILED_JSON");

Expand All @@ -48,12 +48,24 @@ pub struct Args {
help = "Path where the output JSON will be written"
)]
pub output: PathBuf,
#[arg(
long = "output_preimage",
default_value = "dry_run_output_preimage.json",
help = "Path where the output preimage JSON will be written"
)]
pub output_preimage: PathBuf,
#[arg(
long = "print_output",
default_value_t = false,
help = "Print program output to stdout [default: false]"
)]
pub print_output: bool,
#[arg(
long = "print_output_preimage",
default_value_t = false,
help = "Print deserialized output preimage to stdout [default: false]"
)]
pub print_output_preimage: bool,
#[structopt(long = "allow_missing_builtins")]
pub allow_missing_builtins: Option<bool>,
}
Expand All @@ -62,6 +74,7 @@ pub struct Args {
pub fn run(
program_path: PathBuf,
input: HDPDryRunInput,
output_preimage_path: PathBuf,
) -> Result<
(
SyscallHandler<
Expand All @@ -86,6 +99,10 @@ pub fn run(
let program = Program::from_bytes(&program_file, Some(cairo_run_config.entrypoint))?;

let mut hint_processor = CustomHintProcessor::new(input);

// Set output preimage path in execution scopes before running (will be used by the hint)
hint_processor.set_output_preimage_path(output_preimage_path.clone());

let mut cairo_runner = cairo_run_program(&program, &cairo_run_config, &mut hint_processor).map_err(Box::new)?;
debug!("{:?}", cairo_runner.get_execution_resources());

Expand Down Expand Up @@ -119,7 +136,8 @@ pub fn run(
pub async fn run_with_args(args: Args) -> Result<(), Error> {
info!("Starting dry run execution...");
info!("Reading compiled module from: {}", args.compiled_module.display());
let compiled_class: CasmContractClass = serde_json::from_slice(&std::fs::read(args.compiled_module).map_err(Error::IO)?)?;
let compiled_module_path = args.compiled_module.clone();
let compiled_class: CasmContractClass = serde_json::from_slice(&std::fs::read(&compiled_module_path).map_err(Error::IO)?)?;
let params: Vec<Param> = if let Some(path) = args.inputs {
serde_json::from_slice(&std::fs::read(path).map_err(Error::IO)?)?
} else {
Expand All @@ -139,12 +157,17 @@ pub async fn run_with_args(args: Args) -> Result<(), Error> {
params,
injected_state,
},
args.output_preimage.clone(),
)?;

if args.print_output {
println!("{:#?}", output);
}

if args.print_output_preimage {
output_preimage::print_output_preimage(&args.output_preimage, &compiled_module_path)?;
}

std::fs::write(
args.output,
serde_json::to_vec::<
Expand Down
17 changes: 15 additions & 2 deletions crates/sound_run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sound_hint_processor::CustomHintProcessor;
use tokio as _;
use tracing::info;
use tracing_subscriber as _;
use types::{error::Error, param::Param, CasmContractClass, HDPInput, HDPOutput, InjectedState, ProofsData};
use types::{error::Error, output_preimage, param::Param, CasmContractClass, HDPInput, HDPOutput, InjectedState, ProofsData};

use crate::prove::prover_input_from_runner;
pub mod prove;
Expand Down Expand Up @@ -51,6 +51,12 @@ pub struct Args {
help = "Print program output to stdout [default: false]"
)]
pub print_output: bool,
#[arg(
long = "print_output_preimage",
default_value_t = false,
help = "Print deserialized output preimage to stdout [default: false]"
)]
pub print_output_preimage: bool,
#[arg(long = "proof_mode", conflicts_with = "cairo_pie", help = "Configure runner in proof mode")]
pub proof_mode: bool,

Expand Down Expand Up @@ -103,7 +109,8 @@ pub async fn run_with_args(args: Args) -> Result<(), Error> {
info!("Reading compiled module from: {}", args.compiled_module.display());
info!("Reading proofs from: {}", args.proofs.display());

let compiled_class: CasmContractClass = serde_json::from_slice(&std::fs::read(args.compiled_module).map_err(Error::IO)?)?;
let compiled_module_path = args.compiled_module.clone();
let compiled_class: CasmContractClass = serde_json::from_slice(&std::fs::read(&compiled_module_path).map_err(Error::IO)?)?;
let params: Vec<Param> = if let Some(input_path) = args.inputs {
serde_json::from_slice(&std::fs::read(input_path).map_err(Error::IO)?)?
} else {
Expand Down Expand Up @@ -143,6 +150,12 @@ pub async fn run_with_args(args: Args) -> Result<(), Error> {
println!("{:#?}", output);
}

if args.print_output_preimage {
// Use default path for sound run output preimage
let default_preimage_path = PathBuf::from("sound_run_output_preimage.json");
output_preimage::print_output_preimage(&default_preimage_path, &compiled_module_path)?;
}

if let Some(ref relocated_trace) = cairo_runner.relocated_trace {
info!(
"Step count ({}): {:?}",
Expand Down
21 changes: 21 additions & 0 deletions crates/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub mod cairo;
pub mod error;
pub mod keys;
pub mod output_preimage;
pub mod param;
pub mod proofs;

Expand Down Expand Up @@ -49,6 +50,10 @@ pub const OPTIMISM_MAINNET_CHAIN_ID: u128 = 0xa;
pub const OPTIMISM_TESTNET_CHAIN_ID: u128 = 0xaa37dc;
pub const STARKNET_MAINNET_CHAIN_ID: u128 = 0x534e5f4d41494e;
pub const STARKNET_TESTNET_CHAIN_ID: u128 = 0x534e5f5345504f4c4941;
pub const ARBITRUM_MAINNET_CHAIN_ID: u128 = 0xa4b1;
pub const ARBITRUM_TESTNET_CHAIN_ID: u128 = 0x66eee;
pub const BASE_MAINNET_CHAIN_ID: u128 = 0x2105;
pub const BASE_TESTNET_CHAIN_ID: u128 = 0x14a34;

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ProofsData {
Expand Down Expand Up @@ -111,6 +116,10 @@ pub enum ChainIds {
StarknetSepolia,
OptimismMainnet,
OptimismSepolia,
ArbitrumMainnet,
ArbitrumSepolia,
BaseMainnet,
BaseSepolia,
}

impl fmt::Display for ChainIds {
Expand All @@ -122,6 +131,10 @@ impl fmt::Display for ChainIds {
ChainIds::StarknetSepolia => write!(f, "starknet-sepolia"),
ChainIds::OptimismMainnet => write!(f, "optimism-mainnet"),
ChainIds::OptimismSepolia => write!(f, "optimism-sepolia"),
ChainIds::ArbitrumMainnet => write!(f, "arbitrum-mainnet"),
ChainIds::ArbitrumSepolia => write!(f, "arbitrum-sepolia"),
ChainIds::BaseMainnet => write!(f, "base-mainnet"),
ChainIds::BaseSepolia => write!(f, "base-sepolia"),
}
}
}
Expand All @@ -137,6 +150,10 @@ impl FromStr for ChainIds {
"starknet-sepolia" | "starknet_sepolia" | "starknetsepolia" => Ok(Self::StarknetSepolia),
"optimism-mainnet" | "optimism_mainnet" | "optimismmainnet" => Ok(Self::OptimismMainnet),
"optimism-sepolia" | "optimism_sepolia" | "optimismsepolia" => Ok(Self::OptimismSepolia),
"arbitrum-mainnet" | "arbitrum_mainnet" | "arbitrummainnet" => Ok(Self::ArbitrumMainnet),
"arbitrum-sepolia" | "arbitrum_sepolia" | "arbitrumsepolia" => Ok(Self::ArbitrumSepolia),
"base-mainnet" | "base_mainnet" | "basemainnet" => Ok(Self::BaseMainnet),
"base-sepolia" | "base_sepolia" | "basesepolia" => Ok(Self::BaseSepolia),
_ => Err(format!("Invalid chain ID: {}", s)),
}
}
Expand All @@ -151,6 +168,10 @@ impl ChainIds {
STARKNET_TESTNET_CHAIN_ID => Some(Self::StarknetSepolia),
OPTIMISM_MAINNET_CHAIN_ID => Some(Self::OptimismMainnet),
OPTIMISM_TESTNET_CHAIN_ID => Some(Self::OptimismSepolia),
ARBITRUM_MAINNET_CHAIN_ID => Some(Self::ArbitrumMainnet),
ARBITRUM_TESTNET_CHAIN_ID => Some(Self::ArbitrumSepolia),
BASE_MAINNET_CHAIN_ID => Some(Self::BaseMainnet),
BASE_TESTNET_CHAIN_ID => Some(Self::BaseSepolia),
_ => None,
}
}
Expand Down
Loading
Loading