From a7adeb3f88193967a1ee5b8a36a2a233fce0814b Mon Sep 17 00:00:00 2001 From: LucasLvy Date: Thu, 19 Oct 2023 16:26:56 +0200 Subject: [PATCH] feat(os_output): add os_output parsing from run --- src/config.rs | 4 +- src/io/mod.rs | 18 ++++- src/lib.rs | 62 +++++++++++++++- tests/common/mod.rs | 160 ++++++++++++++++++++---------------------- tests/common/utils.rs | 2 +- tests/pie.rs | 4 +- tests/sharp.rs | 2 +- tests/snos.rs | 4 +- 8 files changed, 158 insertions(+), 98 deletions(-) diff --git a/src/config.rs b/src/config.rs index f617fecf2..ae6e16c91 100644 --- a/src/config.rs +++ b/src/config.rs @@ -133,8 +133,8 @@ mod tests { assert_eq!(251, conf.contract_storage_commitment_tree_height); assert_eq!(251, conf.global_state_commitment_tree_height); - assert_eq!(false, conf.constant_gas_price); - assert_eq!(true, conf.enforce_l1_handler_fee); + assert!(!conf.constant_gas_price); + assert!(conf.enforce_l1_handler_fee); assert_eq!(64, conf.event_commitment_tree_height); assert_eq!(64, conf.tx_commitment_tree_height); diff --git a/src/io/mod.rs b/src/io/mod.rs index d3cd7a0da..d41903456 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -8,7 +8,6 @@ use cairo_felt::Felt252; use serde::{Deserialize, Serialize}; use serde_with::serde_as; use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass; -use starknet_api::transaction::{MessageToL1, MessageToL2}; use crate::config::StarknetGeneralConfig; use crate::error::SnOsError; @@ -119,9 +118,22 @@ pub struct StarknetOsOutput { /// The Starknet chain config hash pub config_hash: Felt252, /// List of messages sent to L1 in this block - pub messages_to_l1: Vec, + pub messages_to_l1: Vec, /// List of messages from L1 handled in this block - pub messages_to_l2: Vec, + pub messages_to_l2: Vec, +} +impl StarknetOsOutput { + pub fn new( + prev_state_root: Felt252, + new_state_root: Felt252, + block_number: Felt252, + block_hash: Felt252, + config_hash: Felt252, + messages_to_l1: Vec, + messages_to_l2: Vec, + ) -> Self { + Self { prev_state_root, new_state_root, block_number, block_hash, config_hash, messages_to_l1, messages_to_l2 } + } } impl StarknetOsInput { diff --git a/src/lib.rs b/src/lib.rs index a9a062483..cd43fd888 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,13 +6,17 @@ pub mod sharp; pub mod state; pub mod utils; +use core::panic; use std::fs; use blockifier::block_context::BlockContext; use blockifier::state::state_api::StateReader; +use cairo_felt::Felt252; use cairo_vm::cairo_run::CairoRunConfig; use cairo_vm::types::program::Program; +use cairo_vm::types::relocatable::MaybeRelocatable; use cairo_vm::vm::errors::vm_exception::VmException; +use cairo_vm::vm::runners::builtin_runner::BuiltinRunner; use cairo_vm::vm::runners::cairo_pie::CairoPie; use cairo_vm::vm::runners::cairo_runner::CairoRunner; use cairo_vm::vm::vm_core::VirtualMachine; @@ -20,6 +24,8 @@ use config::StarknetGeneralConfig; use error::SnOsError; use state::SharedState; +use crate::io::StarknetOsOutput; + pub struct SnOsRunner { layout: String, os_path: String, @@ -78,12 +84,64 @@ impl SnOsRunner { .end_run(cairo_run_config.disable_trace_padding, false, &mut vm, &mut sn_hint_processor) .map_err(|e| SnOsError::Runner(e.into()))?; - vm.verify_auto_deductions().map_err(|e| SnOsError::Runner(e.into()))?; - cairo_runner.read_return_values(&mut vm).map_err(|e| SnOsError::Runner(e.into()))?; if cairo_run_config.proof_mode { cairo_runner.finalize_segments(&mut vm).map_err(|e| SnOsError::Runner(e.into()))?; } + // Prepare and check expected output. + // os_output = runner.vm_memory.get_range_as_ints( + // addr=runner.output_builtin.base, size=builtin_end_ptrs[0] - runner.output_builtin.base + // ) + let builtin_end_ptrs = vm.get_return_values(8).map_err(|e| SnOsError::CatchAll(e.to_string()))?; + let output_base = vm + .get_builtin_runners() + .iter() + .find(|&elt| matches!(elt, BuiltinRunner::Output(_))) + .expect("Os vm should have the output builtin") + .base(); + let size_bound_up = match builtin_end_ptrs.last().unwrap() { + MaybeRelocatable::Int(val) => val, + _ => panic!("Value should be an int"), + }; + // Get is input and check that everything is an integer. + let os_output = vm.get_range( + (output_base as isize, 0).into(), + ::from_be_bytes((size_bound_up.clone() - output_base).to_be_bytes()[..8].try_into().unwrap()), + ); + let os_output: Vec = os_output + .iter() + .map(|x| { + if let MaybeRelocatable::Int(val) = x.clone().unwrap().into_owned() { + val + } else { + panic!("Output should be all integers") + } + }) + .collect(); + let prev_state_root = os_output[0].clone(); + let new_state_root = os_output[1].clone(); + let block_number = os_output[2].clone(); + let block_hash = os_output[3].clone(); + let config_hash = os_output[4].clone(); + let os_output = &os_output[5..]; + let messages_to_l1_size = ::from_be_bytes(os_output[0].to_be_bytes()[..8].try_into().unwrap()); + let messages_to_l1 = os_output[1..messages_to_l1_size].to_vec(); + + let os_output = &os_output[messages_to_l1_size + 1..]; + let messages_to_l2 = + os_output[1..::from_be_bytes(os_output[0].to_be_bytes()[..8].try_into().unwrap())].to_vec(); + StarknetOsOutput::new( + prev_state_root, + new_state_root, + block_number, + block_hash, + config_hash, + messages_to_l1, + messages_to_l2, + ); + + vm.verify_auto_deductions().map_err(|e| SnOsError::Runner(e.into()))?; + cairo_runner.read_return_values(&mut vm).map_err(|e| SnOsError::Runner(e.into()))?; cairo_runner.relocate(&mut vm, cairo_run_config.relocate_mem).map_err(|e| SnOsError::Runner(e.into()))?; // Parse the Cairo VM output diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 718efe227..916b8dd54 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -187,7 +187,7 @@ pub fn initial_state( ], version: TransactionVersion::ONE, }); - AccountTransaction::Invoke(fund_account.into()).execute(&mut cache, &block_context, false, true).unwrap(); + AccountTransaction::Invoke(fund_account).execute(&mut cache, &block_context, false, true).unwrap(); let deploy_account_tx = deploy_account_tx(DUMMY_ACCOUNT_HASH_0_12_2, Fee(TESTING_FEE), None, None, &mut nonce_manager); @@ -256,86 +256,76 @@ pub fn prepare_os_test( assert_eq!(expected_addr, contract_addr); } - let mut txs: Vec = Vec::new(); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("set_value").0, - stark_felt!(2_u8), - stark_felt!(85_u8), - stark_felt!(47_u8) - ]); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("set_value").0, - stark_felt!(2_u8), - stark_felt!(81_u8), - stark_felt!(0_u8) - ]); - - txs.push(calldata![ - *contract_addresses[2].0.key(), - selector_from_name("set_value").0, - stark_felt!(2_u8), - stark_felt!(97_u8), - stark_felt!(0_u8) - ]); - - txs.push(calldata![*contract_addresses[1].0.key(), selector_from_name("entry_point").0, stark_felt!(0_u8)]); - - txs.push(calldata![*contract_addresses[0].0.key(), selector_from_name("test_builtins").0, stark_felt!(0_u8)]); - - txs.push(calldata![ - *contract_addresses[1].0.key(), - selector_from_name("test_get_block_timestamp").0, - stark_felt!(1_u8), - stark_felt!(1000_u32) - ]); - - txs.push(calldata![ - *contract_addresses[1].0.key(), - selector_from_name("test_emit_event").0, - stark_felt!(4_u8), - stark_felt!(1_u8), - stark_felt!(1991_u32), - stark_felt!(1_u8), - stark_felt!(2021_u32) - ]); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("test_get_block_number").0, - stark_felt!(1_u32), - stark_felt!(initial_state.block_context.block_number.0 + 1_u64) - ]); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("test_call_contract").0, - stark_felt!(4_u32), - *contract_addresses[0].0.key(), - stark_felt!(selector_from_name("send_message").0), - stark_felt!(1_u8), - stark_felt!(85_u8) - ]); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("test_call_contract").0, - stark_felt!(4_u32), - *contract_addresses[1].0.key(), - stark_felt!(selector_from_name("test_get_caller_address").0), - stark_felt!(1_u8), - *contract_addresses[0].0.key() - ]); - - txs.push(calldata![ - *contract_addresses[0].0.key(), - selector_from_name("test_get_contract_address").0, - stark_felt!(1_u32), - *contract_addresses[0].0.key() - ]); + let mut txs: Vec = vec![ + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("set_value").0, + stark_felt!(2_u8), + stark_felt!(85_u8), + stark_felt!(47_u8) + ], + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("set_value").0, + stark_felt!(2_u8), + stark_felt!(81_u8), + stark_felt!(0_u8) + ], + calldata![ + *contract_addresses[2].0.key(), + selector_from_name("set_value").0, + stark_felt!(2_u8), + stark_felt!(97_u8), + stark_felt!(0_u8) + ], + calldata![*contract_addresses[1].0.key(), selector_from_name("entry_point").0, stark_felt!(0_u8)], + calldata![*contract_addresses[0].0.key(), selector_from_name("test_builtins").0, stark_felt!(0_u8)], + calldata![ + *contract_addresses[1].0.key(), + selector_from_name("test_get_block_timestamp").0, + stark_felt!(1_u8), + stark_felt!(1000_u32) + ], + calldata![ + *contract_addresses[1].0.key(), + selector_from_name("test_emit_event").0, + stark_felt!(4_u8), + stark_felt!(1_u8), + stark_felt!(1991_u32), + stark_felt!(1_u8), + stark_felt!(2021_u32) + ], + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("test_get_block_number").0, + stark_felt!(1_u32), + stark_felt!(initial_state.block_context.block_number.0 + 1_u64) + ], + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("test_call_contract").0, + stark_felt!(4_u32), + *contract_addresses[0].0.key(), + stark_felt!(selector_from_name("send_message").0), + stark_felt!(1_u8), + stark_felt!(85_u8) + ], + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("test_call_contract").0, + stark_felt!(4_u32), + *contract_addresses[1].0.key(), + stark_felt!(selector_from_name("test_get_caller_address").0), + stark_felt!(1_u8), + *contract_addresses[0].0.key() + ], + calldata![ + *contract_addresses[0].0.key(), + selector_from_name("test_get_contract_address").0, + stark_felt!(1_u32), + *contract_addresses[0].0.key() + ], + ]; let delegate_addr = utils::raw_deploy( &mut initial_state, @@ -471,8 +461,8 @@ pub fn prepare_os_test( calldata: tx, version: TransactionVersion::ONE, }); - let tx_info = AccountTransaction::Invoke(account_tx.into()) - .execute(&mut initial_state.cache, &mut initial_state.block_context, false, true) + let tx_info = AccountTransaction::Invoke(account_tx) + .execute(&mut initial_state.cache, &initial_state.block_context, false, true) .unwrap(); exec_info.push(tx_info); } @@ -486,8 +476,8 @@ pub fn prepare_os_test( signature: sig_tx.1, version: TransactionVersion::ONE, }); - let tx_info = AccountTransaction::Invoke(account_tx.into()) - .execute(&mut initial_state.cache, &mut initial_state.block_context, false, true) + let tx_info = AccountTransaction::Invoke(account_tx) + .execute(&mut initial_state.cache, &initial_state.block_context, false, true) .unwrap(); exec_info.push(tx_info); } diff --git a/tests/common/utils.rs b/tests/common/utils.rs index 822f600a7..af4dff8c9 100644 --- a/tests/common/utils.rs +++ b/tests/common/utils.rs @@ -65,7 +65,7 @@ pub fn deprecated_cairo_python_run(program: &str, with_input: bool) -> String { raw.trim_start_matches("Program output:") .trim_start_matches("\n ") .trim_end_matches("\n\n") - .replace(" ", "") + .replace(' ', "") .to_string() } diff --git a/tests/pie.rs b/tests/pie.rs index a8e6ed4d0..4debd3e73 100644 --- a/tests/pie.rs +++ b/tests/pie.rs @@ -62,12 +62,12 @@ fn pie_execution_resources_ok(setup_pie: CairoPie) { fn pie_version_ok(setup_pie: CairoPie) { let version = setup_pie.version; - let version_s = serde_json::to_value(&version).unwrap(); + let version_s = serde_json::to_value(version).unwrap(); assert_eq!(version_s, json!({"cairo_pie": "1.1"})); } #[rstest] fn pie_memory_ok(setup_pie: CairoPie) { - let pie_s = serde_json::to_value(&setup_pie).unwrap(); + let pie_s = serde_json::to_value(setup_pie).unwrap(); assert_eq!(pie_s["memory"], "00000000000000800080ff7f018006400000000000000000000000000000000000000000000000000100000000000080640000000000000000000000000000000000000000000000000000000000000002000000000000800080fd7f0080024800000000000000000000000000000000000000000000000003000000000000800080ff7f018006400000000000000000000000000000000000000000000000000400000000000080c80000000000000000000000000000000000000000000000000000000000000005000000000000800080fd7f0180024800000000000000000000000000000000000000000000000006000000000000800080ff7f0180064000000000000000000000000000000000000000000000000007000000000000802c0100000000000000000000000000000000000000000000000000000000000008000000000000800080fd7f0280024800000000000000000000000000000000000000000000000009000000000000800080fd7f018026480000000000000000000000000000000000000000000000000a0000000000008003000000000000000000000000000000000000000000000000000000000000000b00000000000080fe7fff7fff7f8b20000000000000000000000000000000000000000000000000000000000080008000000000000001000000000000000000000000000000000000000000000000800100000000800080000000000080010000000000000000000000000000000000000000000000008002000000008000800000000000000200000000000000000000000000000000000000000000000080030000000080008064000000000000000000000000000000000000000000000000000000000000000400000000800080c80000000000000000000000000000000000000000000000000000000000000005000000008000802c0100000000000000000000000000000000000000000000000000000000000006000000008000800300000000000100000000000000000000000000000000000000000000000080000000000000018064000000000000000000000000000000000000000000000000000000000000000100000000000180c80000000000000000000000000000000000000000000000000000000000000002000000000001802c01000000000000000000000000000000000000000000000000000000000000"); } diff --git a/tests/sharp.rs b/tests/sharp.rs index e8ba73d39..0b19d87b8 100644 --- a/tests/sharp.rs +++ b/tests/sharp.rs @@ -20,5 +20,5 @@ fn sharp_client_status() { let submit_resp = sharp_client.get_status(TEST_CAIRO_JOB_ID).unwrap(); assert_eq!(submit_resp.version.unwrap(), 1); - assert_eq!(submit_resp.validation_done.unwrap(), true); + assert!(submit_resp.validation_done.unwrap()); } diff --git a/tests/snos.rs b/tests/snos.rs index 78f60a6e1..b182bb4d6 100644 --- a/tests/snos.rs +++ b/tests/snos.rs @@ -17,7 +17,7 @@ use starknet_api::{contract_address, patricia_key, stark_felt}; #[rstest] fn snos_run_test(_load_input: &StarknetOsInput, initial_state: SharedState) { - let snos_runner = SnOsRunner::with_os_path("build/os_debug.json"); + let snos_runner = SnOsRunner::with_os_path("build/fact.json"); let runner_res = snos_runner.run(initial_state); println!("{:#?}", runner_res); } @@ -47,5 +47,5 @@ fn parse_os_input(load_input: &StarknetOsInput) { assert_eq!(felt_str!(TESTING_BLOCK_HASH, 16), load_input.block_hash); assert_eq!(felt_str!(EXPECTED_PREV_ROOT, 16), load_input.contract_state_commitment_info.previous_root); assert_eq!(felt_str!(EXPECTED_UPDATED_ROOT, 16), load_input.contract_state_commitment_info.updated_root); - assert!(load_input.transactions.len() > 0); + assert!(!load_input.transactions.is_empty()); }