Skip to content

Commit

Permalink
feat(os_output): add os_output parsing from run
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLucqs committed Oct 19, 2023
1 parent b190949 commit 3e6d330
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 99 deletions.
4 changes: 2 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 16 additions & 3 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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;
Expand Down Expand Up @@ -119,9 +119,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<MessageToL1>,
pub messages_to_l1: Vec<Felt252>,
/// List of messages from L1 handled in this block
pub messages_to_l2: Vec<MessageToL2>,
pub messages_to_l2: Vec<Felt252>,
}
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<Felt252>,
messages_to_l2: Vec<Felt252>,
) -> Self {
Self { prev_state_root, new_state_root, block_number, block_hash, config_hash, messages_to_l1, messages_to_l2 }
}
}

impl StarknetOsInput {
Expand Down
62 changes: 60 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@ 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;
use config::StarknetGeneralConfig;
use error::SnOsError;
use state::SharedState;

use crate::io::StarknetOsOutput;

pub struct SnOsRunner {
layout: String,
os_path: String,
Expand Down Expand Up @@ -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(),
<usize>::from_be_bytes((size_bound_up.clone() - output_base).to_be_bytes()[..8].try_into().unwrap()),
);
let os_output: Vec<Felt252> = 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 = <usize>::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..<usize>::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
Expand Down
2 changes: 1 addition & 1 deletion src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl<S: StateReader> SharedState<S> {
let mut contract_trie: MerkleTrie<PedersenHash, DEFAULT_STORAGE_TREE_HEIGHT> = MerkleTrie::empty();

for update in updates.clone() {
contract_trie.set(&self.contract_storage, felt_to_bits_api(*update.0.0.key()), update.1).unwrap();
contract_trie.set(&self.contract_storage, felt_to_bits_api(*update.0 .0.key()), update.1).unwrap();
}
self.contract_storage.commit_and_persist(contract_trie, *addr.0.key());

Expand Down
160 changes: 75 additions & 85 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -256,86 +256,76 @@ pub fn prepare_os_test(
assert_eq!(expected_addr, contract_addr);
}

let mut txs: Vec<Calldata> = 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<Calldata> = 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,
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

Expand Down
4 changes: 2 additions & 2 deletions tests/pie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
2 changes: 1 addition & 1 deletion tests/sharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
4 changes: 2 additions & 2 deletions tests/snos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use starknet_api::{contract_address, patricia_key, stark_felt};

#[rstest]
fn snos_run_test(_load_input: &StarknetOsInput, initial_state: SharedState<DictStateReader>) {
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);
}
Expand Down Expand Up @@ -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());
}

0 comments on commit 3e6d330

Please sign in to comment.