Skip to content

Commit

Permalink
Made arg injection to be a hint. (#6579)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Nov 12, 2024
1 parent 5151b81 commit 029ca27
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 89 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/bin/cairo-run/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fn main() -> anyhow::Result<()> {
let result = runner
.run_function_with_starknet_context(
runner.find_function("::main")?,
&[],
vec![],
args.available_gas,
StarknetState::default(),
)
Expand Down
4 changes: 4 additions & 0 deletions crates/cairo-lang-casm/src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,9 @@ pub enum ExternalHint {
/// Relocates a segment from `src` to `dst`.
#[cfg_attr(feature = "parity-scale-codec", codec(index = 0))]
AddRelocationRule { src: ResOperand, dst: ResOperand },
/// Writes a run argument of number `index` to `dst` and on.
#[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
WriteRunParam { index: ResOperand, dst: CellRef },
}

struct DerefOrImmediateFormatter<'a>(&'a DerefOrImmediate);
Expand Down Expand Up @@ -841,6 +844,7 @@ impl PythonicHint for ExternalHint {
let [src, dst] = [src, dst].map(ResOperandAsAddressFormatter);
format!("memory.add_relocation_rule(src_ptr={src}, dest_ptr={dst})")
}
Self::WriteRunParam { .. } => "raise NotImplementedError".to_string(),
}
}
}
1 change: 0 additions & 1 deletion crates/cairo-lang-runnable-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ cairo-lang-sierra-to-casm = { path = "../cairo-lang-sierra-to-casm", version = "
cairo-lang-sierra-type-size = { path = "../cairo-lang-sierra-type-size", version = "~2.8.4" }
cairo-lang-utils = { path = "../cairo-lang-utils", version = "~2.8.4" }
cairo-vm.workspace = true
itertools = { workspace = true, default-features = true }
thiserror.workspace = true

[dev-dependencies]
38 changes: 20 additions & 18 deletions crates/cairo-lang-runnable-utils/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ use cairo_lang_sierra_to_casm::metadata::{
Metadata, MetadataComputationConfig, MetadataError, calc_metadata, calc_metadata_ap_change_only,
};
use cairo_lang_sierra_type_size::{TypeSizeMap, get_type_size_map};
use cairo_lang_utils::casts::IntoOrPanic;
use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
use cairo_vm::types::builtin_name::BuiltinName;
use itertools::Itertools;
use thiserror::Error;

#[derive(Debug, Error)]
Expand Down Expand Up @@ -244,20 +244,9 @@ pub fn create_entry_code_from_params(

let emulated_builtins = UnorderedHashSet::<_>::from_iter([SystemType::ID]);

let mut args_vars = vec![];
for (ty, size) in param_types {
if !builtin_vars.contains_key(ty)
&& !emulated_builtins.contains(ty)
&& ty != &SegmentArenaType::ID
{
args_vars.push((0..*size).map(|_| ctx.alloc_var(false)).collect_vec());
}
}
let got_segment_arena = param_types.iter().any(|(ty, _)| ty == &SegmentArenaType::ID);
let has_post_calculation_loop = got_segment_arena && finalize_for_proof;

// Giving space for the VM to fill the arguments, as well as local params.
let params_size: usize = args_vars.iter().map(Vec::len).sum();
let mut local_exprs = vec![];
if has_post_calculation_loop {
for (ty, size) in return_types {
Expand All @@ -269,7 +258,7 @@ pub fn create_entry_code_from_params(
}
}
}
casm_build_extend!(ctx, ap += params_size + local_exprs.len(););
casm_build_extend!(ctx, ap += local_exprs.len(););
if got_segment_arena {
casm_build_extend! {ctx,
tempvar segment_arena;
Expand All @@ -286,22 +275,35 @@ pub fn create_entry_code_from_params(
// Adding the segment arena to the builtins var map.
builtin_vars.insert(SegmentArenaType::ID, segment_arena);
}
let mut args_vars_iter = args_vars.into_iter();
for (generic_ty, _) in param_types {
let mut unallocated_count = 0;
let mut param_index = 0;
for (generic_ty, ty_size) in param_types {
if let Some(var) = builtin_vars.get(generic_ty).cloned() {
casm_build_extend!(ctx, tempvar _builtin = var;);
} else if emulated_builtins.contains(generic_ty) {
casm_build_extend! {ctx,
tempvar system;
hint AllocSegment into {dst: system};
ap += 1;
};
unallocated_count += ty_size;
} else {
for cell in args_vars_iter.next().unwrap() {
casm_build_extend!(ctx, tempvar _cell = cell;);
if *ty_size > 0 {
casm_build_extend! { ctx,
tempvar first;
const param_index = param_index;
hint ExternalHint::WriteRunParam { index: param_index } into { dst: first };
};
for _ in 1..*ty_size {
casm_build_extend!(ctx, tempvar _cell;);
}
}
param_index += 1;
unallocated_count += ty_size;
};
}
if unallocated_count > 0 {
casm_build_extend!(ctx, ap += unallocated_count.into_or_panic::<usize>(););
}
casm_build_extend! (ctx, let () = call FUNCTION;);
let mut unprocessed_return_size = return_types.iter().map(|(_, size)| size).sum::<i16>();
let mut return_data = vec![];
Expand Down
60 changes: 45 additions & 15 deletions crates/cairo-lang-runner/src/casm_run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use {ark_secp256k1 as secp256k1, ark_secp256r1 as secp256r1};
use self::contract_address::calculate_contract_address;
use self::dict_manager::DictSquashExecScope;
use crate::short_string::{as_cairo_short_string, as_cairo_short_string_ex};
use crate::{Arg, RunResultValue, SierraCasmRunner, StarknetExecutionResources};
use crate::{Arg, RunResultValue, SierraCasmRunner, StarknetExecutionResources, args_size};

#[cfg(test)]
mod test;
Expand Down Expand Up @@ -86,6 +86,11 @@ struct Secp256r1ExecutionScope {
pub struct CairoHintProcessor<'a> {
/// The Cairo runner.
pub runner: Option<&'a SierraCasmRunner>,
/// The user arguments for the run.
///
/// We have a vector of the arguments per parameter, as a parameter type may be composed of
/// several user args.
pub user_args: Vec<Vec<Arg>>,
/// A mapping from a string that represents a hint to the hint object.
pub string_to_hint: HashMap<String, Hint>,
/// The starknet state.
Expand Down Expand Up @@ -419,7 +424,7 @@ impl HintProcessorLogic for CairoHintProcessor<'_> {
return execute_core_hint_base(vm, exec_scopes, core_hint_base);
}
Hint::External(hint) => {
return execute_external_hint(vm, hint);
return self.execute_external_hint(vm, hint);
}
};
match hint {
Expand Down Expand Up @@ -1161,7 +1166,7 @@ impl CairoHintProcessor<'_> {
let mut res = runner
.run_function_with_starknet_context(
function,
&[Arg::Array(calldata.into_iter().map(Arg::Value).collect())],
vec![Arg::Array(calldata.into_iter().map(Arg::Value).collect())],
// The costs of the relevant syscall include `ENTRY_POINT_INITIAL_BUDGET` so we
// need to refund it here before running the entry point to avoid double charging.
Some(*gas_counter + gas_costs::ENTRY_POINT_INITIAL_BUDGET),
Expand Down Expand Up @@ -1291,6 +1296,43 @@ impl CairoHintProcessor<'_> {
insert_value_to_cellref!(vm, output_end, res_segment_end)?;
Ok(())
}

/// Executes an external hint.
fn execute_external_hint(
&self,
vm: &mut VirtualMachine,
core_hint: &ExternalHint,
) -> Result<(), HintError> {
match core_hint {
ExternalHint::AddRelocationRule { src, dst } => Ok(vm.add_relocation_rule(
extract_relocatable(vm, src)?,
extract_relocatable(vm, dst)?,
)?),
ExternalHint::WriteRunParam { index, dst } => {
let index = get_val(vm, index)?.to_usize().expect("Got a bad index.");
let mut stack = vec![(cell_ref_to_relocatable(dst, vm), &self.user_args[index])];
while let Some((mut buffer, values)) = stack.pop() {
for value in values {
match value {
Arg::Value(v) => {
vm.insert_value(buffer, v)?;
buffer += 1;
}
Arg::Array(arr) => {
let arr_buffer = vm.add_memory_segment();
stack.push((arr_buffer, arr));
vm.insert_value(buffer, arr_buffer)?;
buffer += 1;
vm.insert_value(buffer, (arr_buffer + args_size(arr))?)?;
buffer += 1;
}
}
}
}
Ok(())
}
}
}
}

/// Extracts an array of felt252s from a vector of such.
Expand Down Expand Up @@ -2131,18 +2173,6 @@ pub fn execute_core_hint(
Ok(())
}

/// Executes an external hint.
fn execute_external_hint(
vm: &mut VirtualMachine,
core_hint: &ExternalHint,
) -> Result<(), HintError> {
match core_hint {
ExternalHint::AddRelocationRule { src, dst } => Ok(
vm.add_relocation_rule(extract_relocatable(vm, src)?, extract_relocatable(vm, dst)?)?
),
}
}

/// Reads a range of `Felt252`s from the VM.
fn read_felts(
vm: &mut VirtualMachine,
Expand Down
2 changes: 2 additions & 0 deletions crates/cairo-lang-runner/src/casm_run/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ fn test_runner(function: CasmContext, n_returns: usize, expected: &[i128]) {
let (hints_dict, string_to_hint) = build_hints_dict(&program.hints);
let mut hint_processor = CairoHintProcessor {
runner: None,
user_args: vec![],
string_to_hint,
starknet_state: StarknetState::default(),
run_resources: RunResources::default(),
Expand Down Expand Up @@ -151,6 +152,7 @@ fn test_allocate_segment() {
let (hints_dict, string_to_hint) = build_hints_dict(&program.hints);
let mut hint_processor = CairoHintProcessor {
runner: None,
user_args: vec![],
string_to_hint,
starknet_state: StarknetState::default(),
run_resources: RunResources::default(),
Expand Down
Loading

0 comments on commit 029ca27

Please sign in to comment.