From 1da7ceb1506e86b385798606832532ad77a16648 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Mon, 2 Dec 2024 14:44:40 +0100 Subject: [PATCH] contract inputs & refactors --- Cargo.lock | 1 + Cargo.toml | 1 + cairo_vm_hints/Cargo.toml | 1 + cairo_vm_hints/src/hint_processor/input.rs | 19 ++++--- cairo_vm_hints/src/hint_processor/mod.rs | 2 + cairo_vm_hints/src/hint_processor/models.rs | 22 ++++++++ cairo_vm_hints/src/hint_processor/output.rs | 9 ++-- .../hints/lib/contract_bootloader/builtins.rs | 4 +- .../lib/contract_bootloader/contract_class.rs | 3 +- .../src/hints/lib/contract_bootloader/mod.rs | 1 + .../hints/lib/contract_bootloader/params.rs | 52 +++++++++++++++++++ cairo_vm_hints/src/hints/lib/print.rs | 19 +++---- cairo_vm_hints/src/hints/vars.rs | 5 ++ .../contract_dry_run.cairo | 37 ++++++++----- 14 files changed, 139 insertions(+), 37 deletions(-) create mode 100644 cairo_vm_hints/src/hint_processor/models.rs create mode 100644 cairo_vm_hints/src/hints/lib/contract_bootloader/params.rs diff --git a/Cargo.lock b/Cargo.lock index d01c25b1..215c7996 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1163,6 +1163,7 @@ dependencies = [ "num-bigint", "num-traits", "rand", + "serde", "serde_json", "sha3", "starknet-crypto 0.7.3", diff --git a/Cargo.toml b/Cargo.toml index 0c82d394..d76a9f4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ hex = "0.4.3" num-bigint = "0.4.6" num-traits = "0.2.19" rand = "0.8" +serde = "1.0.215" serde_json = "1.0.132" sha3 = "0.10.8" starknet-crypto = "0.7.2" diff --git a/cairo_vm_hints/Cargo.toml b/cairo_vm_hints/Cargo.toml index cc7b248d..d8ece114 100644 --- a/cairo_vm_hints/Cargo.toml +++ b/cairo_vm_hints/Cargo.toml @@ -15,6 +15,7 @@ num-bigint.workspace = true num-traits.workspace = true rand.workspace = true serde_json.workspace = true +serde.workspace = true sha3.workspace = true starknet-crypto.workspace = true starknet-types-core.workspace = true diff --git a/cairo_vm_hints/src/hint_processor/input.rs b/cairo_vm_hints/src/hint_processor/input.rs index 875355a8..a34293a1 100644 --- a/cairo_vm_hints/src/hint_processor/input.rs +++ b/cairo_vm_hints/src/hint_processor/input.rs @@ -1,6 +1,8 @@ +use super::{ + models::{HDPDryRunInput, Param}, + CustomHintProcessor, +}; use crate::hints::vars; - -use super::CustomHintProcessor; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use cairo_vm::{ hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData, @@ -10,7 +12,7 @@ use cairo_vm::{ }; use std::collections::HashMap; -pub const HINT_INPUT: &str = "from tools.py.schema import HDPDryRunInput\ncompiled_class = HDPDryRunInput.Schema().load(program_input).modules[0].module_class"; +pub const HINT_INPUT: &str = "from tools.py.schema import HDPDryRunInput\ndry_run_input = HDPDryRunInput.Schema().load(program_input)\nparams = dry_run_input.params\ncompiled_class = dry_run_input.compiled_class"; impl CustomHintProcessor { pub fn hint_input( @@ -20,10 +22,13 @@ impl CustomHintProcessor { _hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let contract_class: CasmContractClass = - serde_json::from_value(self.private_inputs[vars::scopes::COMPILED_CLASS].clone()) - .map_err(|_| HintError::WrongHintData)?; - exec_scopes.insert_value::(vars::scopes::COMPILED_CLASS, contract_class); + let hdp_dry_run_input: HDPDryRunInput = serde_json::from_value(self.private_inputs.clone()) + .map_err(|_| HintError::WrongHintData)?; + exec_scopes.insert_value::>(vars::scopes::PARAMS, hdp_dry_run_input.params); + exec_scopes.insert_value::( + vars::scopes::COMPILED_CLASS, + hdp_dry_run_input.compiled_class, + ); Ok(()) } } diff --git a/cairo_vm_hints/src/hint_processor/mod.rs b/cairo_vm_hints/src/hint_processor/mod.rs index db00a187..390019c0 100644 --- a/cairo_vm_hints/src/hint_processor/mod.rs +++ b/cairo_vm_hints/src/hint_processor/mod.rs @@ -1,4 +1,5 @@ pub mod input; +pub mod models; pub mod output; use crate::hints::{lib, vars}; @@ -76,6 +77,7 @@ impl CustomHintProcessor { let mut hints = HashMap::::new(); hints.insert(lib::contract_bootloader::contract_class::LOAD_CONTRACT_CLASS.into(), lib::contract_bootloader::contract_class::load_contract_class); hints.insert(lib::contract_bootloader::dict_manager::DICT_MANAGER_CREATE.into(), lib::contract_bootloader::dict_manager::dict_manager_create); + hints.insert(lib::contract_bootloader::params::LOAD_PARMAS.into(), lib::contract_bootloader::params::load_parmas); hints.insert(lib::contract_bootloader::scopes::ENTER_SCOPE_SYSCALL_HANDLER.into(), lib::contract_bootloader::scopes::enter_scope_syscall_handler); hints.insert(lib::contract_bootloader::syscall_handler::SYSCALL_HANDLER_CREATE.into(), lib::contract_bootloader::syscall_handler::syscall_handler_create); hints.insert(lib::contract_bootloader::syscall_handler::DRY_RUN_SYSCALL_HANDLER_CREATE.into(), lib::contract_bootloader::syscall_handler::dry_run_syscall_handler_create); diff --git a/cairo_vm_hints/src/hint_processor/models.rs b/cairo_vm_hints/src/hint_processor/models.rs new file mode 100644 index 00000000..ab11a28c --- /dev/null +++ b/cairo_vm_hints/src/hint_processor/models.rs @@ -0,0 +1,22 @@ +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use cairo_vm::Felt252; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Param { + pub visibility: Visibility, + pub value: Felt252, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum Visibility { + Public, + Private, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct HDPDryRunInput { + pub params: Vec, + pub compiled_class: CasmContractClass, +} diff --git a/cairo_vm_hints/src/hint_processor/output.rs b/cairo_vm_hints/src/hint_processor/output.rs index 8369c4b8..7321d3d9 100644 --- a/cairo_vm_hints/src/hint_processor/output.rs +++ b/cairo_vm_hints/src/hint_processor/output.rs @@ -1,4 +1,5 @@ use super::CustomHintProcessor; +use crate::hints::vars; use cairo_vm::{ hint_processor::builtin_hint_processor::{ builtin_hint_processor_definition::HintProcessorData, @@ -10,8 +11,7 @@ use cairo_vm::{ }; use std::collections::HashMap; -pub const HINT_OUTPUT: &str = - "print(\"result.low\", hex(ids.result.low))\nprint(\"result.high\", hex(ids.result.high))"; +pub const HINT_OUTPUT: &str = "print(\"result\", [hex(ids.result.low), hex(ids.result.high)])"; impl CustomHintProcessor { pub fn hint_output( @@ -22,7 +22,7 @@ impl CustomHintProcessor { _constants: &HashMap, ) -> Result<(), HintError> { let result_ptr = get_relocatable_from_var_name( - "result", + vars::ids::RESULT, vm, &hint_data.ids_data, &hint_data.ap_tracking, @@ -34,8 +34,7 @@ impl CustomHintProcessor { .map(|v| v.get_int().unwrap()) .collect::>(); - println!("result.low: {}", result[0]); - println!("result.high: {}", result[1]); + println!("result: {}, {}", result[0], result[1]); Ok(()) } } diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/builtins.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/builtins.rs index 0168f7fb..6d45df59 100644 --- a/cairo_vm_hints/src/hints/lib/contract_bootloader/builtins.rs +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/builtins.rs @@ -13,7 +13,7 @@ use cairo_vm::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, Felt252, }; -use std::{any::Any, collections::HashMap, ops::AddAssign}; +use std::{any::Any, collections::HashMap}; pub const UPDATE_BUILTIN_PTRS: &str = "from starkware.starknet.core.os.os_utils import update_builtin_pointers\n\n# Fill the values of all builtin pointers after the current transaction.\nids.return_builtin_ptrs = segments.gen_arg(\n update_builtin_pointers(\n memory=memory,\n n_builtins=ids.n_builtins,\n builtins_encoding_addr=ids.builtin_params.builtin_encodings.address_,\n n_selected_builtins=ids.n_selected_builtins,\n selected_builtins_encoding_addr=ids.selected_encodings,\n orig_builtin_ptrs_addr=ids.builtin_ptrs.selectable.address_,\n selected_builtin_ptrs_addr=ids.selected_ptrs,\n ),\n )"; @@ -139,7 +139,7 @@ pub fn select_builtin( )?; if select_builtin { - n_selected_builtins.add_assign(-Felt252::ONE); + *n_selected_builtins -= Felt252::ONE; } Ok(()) diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/contract_class.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/contract_class.rs index 1ae2fd03..ba808445 100644 --- a/cairo_vm_hints/src/hints/lib/contract_bootloader/contract_class.rs +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/contract_class.rs @@ -1,3 +1,4 @@ +use crate::hints::vars; use cairo_lang_starknet_classes::casm_contract_class::{CasmContractClass, CasmContractEntryPoint}; use cairo_vm::{ hint_processor::builtin_hint_processor::{ @@ -13,8 +14,6 @@ use cairo_vm::{ }; use std::collections::HashMap; -use crate::hints::vars; - const COMPILED_CLASS_V1: Felt252 = Felt252::from_hex_unchecked("0x434f4d50494c45445f434c4153535f5631"); diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/mod.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/mod.rs index d1412b53..e9e82720 100644 --- a/cairo_vm_hints/src/hints/lib/contract_bootloader/mod.rs +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/mod.rs @@ -1,6 +1,7 @@ pub mod builtins; pub mod contract_class; pub mod dict_manager; +pub mod params; pub mod program; pub mod scopes; pub mod syscall_handler; diff --git a/cairo_vm_hints/src/hints/lib/contract_bootloader/params.rs b/cairo_vm_hints/src/hints/lib/contract_bootloader/params.rs new file mode 100644 index 00000000..91bdb8a3 --- /dev/null +++ b/cairo_vm_hints/src/hints/lib/contract_bootloader/params.rs @@ -0,0 +1,52 @@ +use crate::{hint_processor::models::Param, hints::vars}; +use cairo_vm::{ + hint_processor::builtin_hint_processor::{ + builtin_hint_processor_definition::HintProcessorData, + hint_utils::{get_ptr_from_var_name, insert_value_from_var_name}, + }, + types::{exec_scope::ExecutionScopes, relocatable::Relocatable}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use std::collections::HashMap; + +pub const LOAD_PARMAS: &str = "ids.params_len = len(params)\nsegments.write_arg(ids.params, [param.value for param in params])"; + +pub fn load_parmas( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let params = exec_scopes.get::>(vars::scopes::PARAMS)?; + insert_value_from_var_name( + vars::ids::PARAMS_LEN, + params.len(), + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + let params_base = get_ptr_from_var_name( + vars::ids::PARAMS, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + write_params(vm, params_base, params)?; + + Ok(()) +} + +pub fn write_params( + vm: &mut VirtualMachine, + ptr: Relocatable, + params: Vec, +) -> Result<(), HintError> { + for (idx, param) in params.into_iter().enumerate() { + vm.insert_value((ptr + idx)?, param.value)?; + } + + Ok(()) +} diff --git a/cairo_vm_hints/src/hints/lib/print.rs b/cairo_vm_hints/src/hints/lib/print.rs index 59f9a764..75c63581 100644 --- a/cairo_vm_hints/src/hints/lib/print.rs +++ b/cairo_vm_hints/src/hints/lib/print.rs @@ -1,3 +1,4 @@ +use crate::hints::vars; use cairo_vm::{ hint_processor::builtin_hint_processor::{ builtin_hint_processor_definition::HintProcessorData, hint_utils::get_integer_from_var_name, @@ -16,14 +17,14 @@ pub fn program_hash( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - println!( - "program_hash: {}", - get_integer_from_var_name( - "program_hash", - vm, - &hint_data.ids_data, - &hint_data.ap_tracking - )? - ); + let program_hash = get_integer_from_var_name( + vars::ids::PROGRAM_HASH, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + println!("program_hash: {}", program_hash); + Ok(()) } diff --git a/cairo_vm_hints/src/hints/vars.rs b/cairo_vm_hints/src/hints/vars.rs index 38e0ca48..be27ee93 100644 --- a/cairo_vm_hints/src/hints/vars.rs +++ b/cairo_vm_hints/src/hints/vars.rs @@ -2,6 +2,7 @@ pub mod scopes { pub(crate) const COMPILED_CLASS: &str = "compiled_class"; pub(crate) const DICT_MANAGER: &str = "dict_manager"; pub(crate) const N_SELECTED_BUILTINS: &str = "n_selected_builtins"; + pub(crate) const PARAMS: &str = "params"; pub(crate) const SYSCALL_HANDLER: &str = "syscall_handler"; } @@ -19,8 +20,12 @@ pub mod ids { pub(crate) const N_BUILTINS: &str = "n_builtins"; pub(crate) const N_PROCESSED_WORDS: &str = "ids.n_processed_words"; pub(crate) const N_SELECTED_BUILTINS: &str = "n_selected_builtins"; + pub(crate) const PARAMS_LEN: &str = "params_len"; + pub(crate) const PARAMS: &str = "params"; + pub(crate) const PROGRAM_HASH: &str = "program_hash"; pub(crate) const Q: &str = "ids.q"; pub(crate) const R: &str = "ids.r"; + pub(crate) const RESULT: &str = "result"; pub(crate) const RETURN_BUILTIN_PTRS: &str = "return_builtin_ptrs"; pub(crate) const RLP: &str = "ids.rlp"; pub(crate) const SELECT_BUILTIN: &str = "select_builtin"; diff --git a/src/contract_bootloader/contract_dry_run.cairo b/src/contract_bootloader/contract_dry_run.cairo index 98b40240..32419165 100644 --- a/src/contract_bootloader/contract_dry_run.cairo +++ b/src/contract_bootloader/contract_dry_run.cairo @@ -17,6 +17,11 @@ from contract_bootloader.contract_class.compiled_class import CompiledClass, com from contract_bootloader.contract_bootloader import run_contract_bootloader, compute_program_hash from starkware.cairo.common.memcpy import memcpy +struct DryRunOutput { + program_hash: felt, + result: Uint256, +} + func main{ output_ptr: felt*, pedersen_ptr: HashBuiltin*, @@ -29,22 +34,27 @@ func main{ }() { alloc_locals; - local inputs_len: felt = 0; - let (inputs) = alloc(); - %{ from tools.py.schema import HDPDryRunInput - compiled_class = HDPDryRunInput.Schema().load(program_input).modules[0].module_class + dry_run_input = HDPDryRunInput.Schema().load(program_input) + params = dry_run_input.params + compiled_class = dry_run_input.compiled_class %} + local params_len: felt; + let (params) = alloc(); local compiled_class: CompiledClass*; - // Fetch contract data form hints. %{ from contract_bootloader.contract_class.compiled_class_hash_utils import get_compiled_class_struct ids.compiled_class = segments.gen_arg(get_compiled_class_struct(compiled_class=compiled_class)) %} + %{ + ids.params_len = len(params) + segments.write_arg(ids.params, [param.value for param in params]) + %} + let (builtin_costs: felt*) = alloc(); assert builtin_costs[0] = 0; assert builtin_costs[1] = 0; @@ -90,8 +100,8 @@ func main{ assert calldata[2] = nondet %{ ids.starknet_memorizer.address_.segment_index %}; assert calldata[3] = nondet %{ ids.starknet_memorizer.address_.offset %}; - memcpy(dst=calldata + 4, src=inputs, len=inputs_len); - let calldata_size = 4 + inputs_len; + memcpy(dst=calldata + 4, src=params, len=params_len); + let calldata_size = 4 + params_len; let (evm_decoder_ptr: felt***) = alloc(); let (starknet_decoder_ptr: felt***) = alloc(); @@ -103,14 +113,17 @@ func main{ compiled_class=compiled_class, calldata_size=calldata_size, calldata=calldata, dry_run=1 ); } - assert retdata_size = 2; local result: Uint256 = Uint256(low=retdata[0], high=retdata[1]); - %{ - print("result.low", hex(ids.result.low)) - print("result.high", hex(ids.result.high)) - %} + %{ print("result", [hex(ids.result.low), hex(ids.result.high)]) %} + + // Write DryRunOutput to output. + assert [cast(output_ptr, DryRunOutput*)] = DryRunOutput( + program_hash=program_hash, + result=result + ); + let output_ptr = output_ptr + DryRunOutput.SIZE; return (); }