diff --git a/README.md b/README.md
index d11991ec..03d280d9 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,7 @@
-## [Overview](https://hackmd.io/@pragma/ByP-iux1T)
-
-Rust Library for running the Starknet OS via the [Cairo VM](https://github.com/lambdaclass/cairo-vm).
+Rust Library for running the [Starknet OS](https://hackmd.io/@pragma/ByP-iux1T) via the [Cairo VM](https://github.com/lambdaclass/cairo-vm).
## Test Setup
@@ -17,15 +15,14 @@ Rust Library for running the Starknet OS via the [Cairo VM](https://github.com/l
cargo test
```
-### Reset Tests
+**Reset Tests**
```bash
./scripts/teardown-tests.sh
```
-### Debug Single Cairo Program
+**Debug Single Cairo Program**
```bash
./scripts/debug-hint.sh load_deprecated_class
```
-
\ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
index ae6e16c9..8ae6184d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -10,13 +10,15 @@ use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use starknet_api::block::{BlockNumber, BlockTimestamp};
use starknet_api::core::{ChainId, ContractAddress, PatriciaKey};
-use starknet_api::hash::StarkHash;
+use starknet_api::hash::{pedersen_hash_array, StarkFelt, StarkHash};
use starknet_api::{contract_address, patricia_key};
+use starknet_crypto::FieldElement;
use crate::error::SnOsError;
const DEFAULT_CONFIG_PATH: &str = "cairo-lang/src/starkware/starknet/definitions/general_config.yml";
+pub const STARKNET_OS_CONFIG_HASH_VERSION: &str = "StarknetOsConfig1";
pub const DEFAULT_LAYOUT: &str = "starknet_with_keccak";
pub const DEFAULT_COMPILED_OS: &str = "build/os_latest.json";
pub const DEFAULT_INPUT_PATH: &str = "build/input.json";
@@ -35,6 +37,16 @@ pub struct StarknetOsConfig {
pub fee_token_address: ContractAddress,
}
+impl StarknetOsConfig {
+ pub fn hash(&self) -> StarkHash {
+ pedersen_hash_array(&[
+ StarkFelt::from(FieldElement::from_byte_slice_be(STARKNET_OS_CONFIG_HASH_VERSION.as_bytes()).unwrap()),
+ StarkFelt::from(u128::from_str_radix(&self.chain_id.0, 16).unwrap()),
+ *self.fee_token_address.0.key(),
+ ])
+ }
+}
+
#[derive(Debug, Serialize, Clone, Deserialize)]
pub struct StarknetGeneralConfig {
pub starknet_os_config: StarknetOsConfig,
diff --git a/src/error.rs b/src/error.rs
index 7e5b0c43..6f402cd6 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -15,6 +15,8 @@ pub enum SnOsError {
SharpRequest(String),
#[error("Starknet Os Runner Error: {0}")]
Runner(CairoRunError),
+ #[error("SnOs Output Error: {0}")]
+ Output(String),
}
#[derive(thiserror::Error, Clone, Debug)]
diff --git a/src/io/mod.rs b/src/io/mod.rs
index a9a6a25c..00001a5f 100644
--- a/src/io/mod.rs
+++ b/src/io/mod.rs
@@ -1,4 +1,5 @@
pub mod classes;
+pub mod output;
use std::collections::HashMap;
use std::io::Write;
@@ -32,6 +33,19 @@ pub struct StarknetOsInput {
pub block_hash: Felt252,
}
+impl StarknetOsInput {
+ pub fn load(path: &str) -> Self {
+ let raw_input = fs::read_to_string(path::PathBuf::from(path)).unwrap();
+ serde_json::from_str(&raw_input).unwrap()
+ }
+ pub fn dump(&self, path: &str) -> Result<(), SnOsError> {
+ fs::File::create(path)
+ .unwrap()
+ .write_all(&serde_json::to_vec(&self).unwrap())
+ .map_err(|e| SnOsError::CatchAll(format!("{e}")))
+ }
+}
+
#[serde_as]
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct CommitmentInfo {
@@ -127,43 +141,3 @@ pub struct StarknetOsOutput {
/// List of the newly declared contract classes.
pub contract_class_diff: Vec,
}
-
-impl StarknetOsOutput {
- #[allow(clippy::too_many_arguments)]
- 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,
- state_updates: Vec,
- contract_class_diff: Vec,
- ) -> Self {
- Self {
- prev_state_root,
- new_state_root,
- block_number,
- block_hash,
- config_hash,
- messages_to_l1,
- messages_to_l2,
- state_updates,
- contract_class_diff,
- }
- }
-}
-
-impl StarknetOsInput {
- pub fn load(path: &str) -> Self {
- let raw_input = fs::read_to_string(path::PathBuf::from(path)).unwrap();
- serde_json::from_str(&raw_input).unwrap()
- }
- pub fn dump(&self, path: &str) -> Result<(), SnOsError> {
- fs::File::create(path)
- .unwrap()
- .write_all(&serde_json::to_vec(&self).unwrap())
- .map_err(|e| SnOsError::CatchAll(format!("{e}")))
- }
-}
diff --git a/src/io/output.rs b/src/io/output.rs
new file mode 100644
index 00000000..0d6aa6bd
--- /dev/null
+++ b/src/io/output.rs
@@ -0,0 +1,66 @@
+use cairo_felt::Felt252;
+use cairo_vm::types::relocatable::MaybeRelocatable;
+use cairo_vm::vm::runners::builtin_runner::BuiltinRunner;
+use cairo_vm::vm::vm_core::VirtualMachine;
+
+use super::StarknetOsOutput;
+use crate::error::SnOsError;
+use crate::utils::felt_vm2usize;
+
+const PREVIOUS_MERKLE_UPDATE_OFFSET: usize = 0;
+const NEW_MERKLE_UPDATE_OFFSET: usize = 1;
+const BLOCK_NUMBER_OFFSET: usize = 2;
+const BLOCK_HASH_OFFSET: usize = 3;
+const CONFIG_HASH_OFFSET: usize = 4;
+const HEADER_SIZE: usize = 5;
+
+impl StarknetOsOutput {
+ pub fn from_run(vm: &VirtualMachine) -> Result {
+ // 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 raw_output = vm
+ .get_range((output_base as isize, 0).into(), felt_vm2usize(Some(&(size_bound_up.clone() - output_base)))?);
+ let raw_output: Vec = raw_output
+ .iter()
+ .map(|x| {
+ if let MaybeRelocatable::Int(val) = x.clone().unwrap().into_owned() {
+ val
+ } else {
+ panic!("Output should be all integers")
+ }
+ })
+ .collect();
+
+ decode_output(raw_output)
+ }
+}
+
+pub fn decode_output(mut os_output: Vec) -> Result {
+ let header: Vec = os_output.drain(..HEADER_SIZE).collect();
+
+ Ok(StarknetOsOutput {
+ prev_state_root: header[PREVIOUS_MERKLE_UPDATE_OFFSET].clone(),
+ new_state_root: header[NEW_MERKLE_UPDATE_OFFSET].clone(),
+ block_number: header[BLOCK_NUMBER_OFFSET].clone(),
+ block_hash: header[BLOCK_HASH_OFFSET].clone(),
+ config_hash: header[CONFIG_HASH_OFFSET].clone(),
+ messages_to_l1: os_output.drain(1..felt_vm2usize(os_output.first())?).collect(),
+ messages_to_l2: os_output.drain(1..felt_vm2usize(os_output.first())?).collect(),
+ state_updates: os_output.drain(1..felt_vm2usize(os_output.first())?).collect(),
+ contract_class_diff: os_output.drain(1..felt_vm2usize(os_output.first())?).collect(),
+ })
+}
diff --git a/src/lib.rs b/src/lib.rs
index 415ad40a..fd69333f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,26 +6,21 @@ 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 io::StarknetOsOutput;
use state::SharedState;
-use crate::io::StarknetOsOutput;
-
pub struct SnOsRunner {
layout: String,
os_path: String,
@@ -34,22 +29,6 @@ pub struct SnOsRunner {
}
impl SnOsRunner {
- pub fn with_layout(layout: &str) -> Self {
- Self { layout: layout.to_string(), ..Self::default() }
- }
-
- pub fn with_os_path(os_path: &str) -> Self {
- Self { os_path: os_path.to_string(), ..Self::default() }
- }
-
- pub fn with_input_path(input_path: &str) -> Self {
- Self { input_path: input_path.to_string(), ..Self::default() }
- }
-
- pub fn with_block_context(block_context: BlockContext) -> Self {
- Self { block_context, ..Self::default() }
- }
-
pub fn run(&self, shared_state: SharedState) -> Result {
// Init CairoRunConfig
let cairo_run_config = CairoRunConfig {
@@ -91,68 +70,9 @@ impl SnOsRunner {
}
// 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..1 + messages_to_l1_size].to_vec();
-
- let os_output = &os_output[messages_to_l1_size + 1..];
- let messages_to_l2_size = ::from_be_bytes(os_output[0].to_be_bytes()[..8].try_into().unwrap());
- let messages_to_l2 = os_output[1..1 + messages_to_l2_size].to_vec();
- let os_output = &os_output[messages_to_l2_size + 1..];
-
- let state_updates_size = ::from_be_bytes(os_output[0].to_be_bytes()[..8].try_into().unwrap());
- let state_updates = os_output[1..1 + state_updates_size].to_vec();
- let os_output = &os_output[state_updates_size + 1..];
-
- let contract_class_diff_size = ::from_be_bytes(os_output[0].to_be_bytes()[..8].try_into().unwrap());
- let contract_class_diff = os_output[1..1 + contract_class_diff_size].to_vec();
- let real_output = StarknetOsOutput::new(
- prev_state_root,
- new_state_root,
- block_number,
- block_hash,
- config_hash,
- messages_to_l1,
- messages_to_l2,
- state_updates,
- contract_class_diff,
- );
- println!("{:?}", real_output);
+ let _os_output = StarknetOsOutput::from_run(&vm)?;
+
+ println!("{:?}", _os_output);
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()))?;
@@ -163,6 +83,22 @@ impl SnOsRunner {
Ok(pie)
}
+
+ pub fn with_layout(layout: &str) -> Self {
+ Self { layout: layout.to_string(), ..Self::default() }
+ }
+
+ pub fn with_os_path(os_path: &str) -> Self {
+ Self { os_path: os_path.to_string(), ..Self::default() }
+ }
+
+ pub fn with_input_path(input_path: &str) -> Self {
+ Self { input_path: input_path.to_string(), ..Self::default() }
+ }
+
+ pub fn with_block_context(block_context: BlockContext) -> Self {
+ Self { block_context, ..Self::default() }
+ }
}
impl Default for SnOsRunner {
diff --git a/src/utils.rs b/src/utils.rs
index 5f3cc254..fd3d88ae 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -18,6 +18,7 @@ use starknet_api::hash::{pedersen_hash, StarkFelt, StarkHash};
use starknet_api::stark_felt;
use crate::config::DEFAULT_COMPILER_VERSION;
+use crate::error::SnOsError;
lazy_static! {
static ref RE: Regex = Regex::new(r"^[A-Fa-f0-9]+$").unwrap();
@@ -60,6 +61,17 @@ pub fn felt_api2vm(felt: StarkFelt) -> Felt252 {
felt_str!(felt.to_string().trim_start_matches("0x"), 16)
}
+pub fn felt_vm2usize(felt_op: Option<&Felt252>) -> Result {
+ match felt_op {
+ Some(felt) => {
+ let big_num: u16 = felt.to_bigint().try_into().map_err(|e| SnOsError::Output(format!("{e}")))?;
+
+ Ok(big_num.into())
+ }
+ None => Err(SnOsError::CatchAll("no length available".to_string())),
+ }
+}
+
pub fn deprecated_class_vm2api(class: ContractClassV0) -> DeprecatedContractClass {
DeprecatedContractClass {
abi: None,
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 916b8dd5..2f3d9715 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -1,4 +1,4 @@
-pub mod serde;
+pub mod serde_utils;
pub mod utils;
use std::collections::HashMap;
@@ -27,7 +27,8 @@ use cairo_vm::vm::runners::cairo_runner::CairoRunner;
use cairo_vm::vm::vm_core::VirtualMachine;
use rstest::{fixture, rstest};
use snos::config::{StarknetGeneralConfig, DEFAULT_FEE_TOKEN_ADDR, DEFAULT_INPUT_PATH};
-use snos::io::StarknetOsInput;
+use snos::io::output::decode_output;
+use snos::io::{StarknetOsInput, StarknetOsOutput};
use snos::state::SharedState;
use starknet_api::block::{BlockNumber, BlockTimestamp};
use starknet_api::core::{calculate_contract_address, ClassHash, ContractAddress, PatriciaKey};
@@ -71,7 +72,7 @@ pub const EXPECTED_UPDATED_ROOT: &str = "482c9ce8a99afddc9777ff048520fcbfab6c038
#[fixture]
#[once]
pub fn load_and_write_input() {
- let os_input = serde::StarknetOsInputUtil::load("tests/common/os_input.json");
+ let os_input = serde_utils::StarknetOsInputUtil::load("tests/common/os_input.json");
os_input.dump(DEFAULT_INPUT_PATH).unwrap();
}
@@ -501,48 +502,10 @@ pub fn prepare_os_test(
(initial_state, exec_info)
}
-#[rstest]
-fn validate_prepare(prepare_os_test: (SharedState, Vec)) {
- let mut shared_state = prepare_os_test.0;
- let diff = shared_state.cache.to_state_diff();
-
- let addr_1 = contract_address!("46fd0893101585e0c7ebd3caf8097b179f774102d6373760c8f60b1a5ef8c92");
- let addr_1_updates = diff.storage_updates.get(&addr_1).unwrap();
- assert_eq!(5, addr_1_updates.len());
- assert_eq!(&stark_felt!(47_u32), addr_1_updates.get(&StorageKey(patricia_key!(85_u32))).unwrap());
- assert_eq!(&stark_felt!(543_u32), addr_1_updates.get(&StorageKey(patricia_key!(321_u32))).unwrap());
- assert_eq!(&stark_felt!(666_u32), addr_1_updates.get(&StorageKey(patricia_key!(444_u32))).unwrap());
-
- let addr_2 = contract_address!("4e9665675ca1ac12820b7aff2f44fec713e272efcd3f20aa0fd8ca277f25dc6");
- let addr_2_updates = diff.storage_updates.get(&addr_2).unwrap();
- assert_eq!(&stark_felt!(1_u32), addr_2_updates.get(&StorageKey(patricia_key!(15_u32))).unwrap());
- assert_eq!(&stark_felt!(987_u32), addr_2_updates.get(&StorageKey(patricia_key!(111_u32))).unwrap());
- assert_eq!(&stark_felt!(888_u32), addr_2_updates.get(&StorageKey(patricia_key!(555_u32))).unwrap());
- assert_eq!(&stark_felt!(999_u32), addr_2_updates.get(&StorageKey(patricia_key!(666_u32))).unwrap());
-
- let delegate_addr = contract_address!("238e6b5dffc9f0eb2fe476855d0cd1e9e034e5625663c7eda2d871bd4b6eac0");
- let delegate_addr_updates = diff.storage_updates.get(&delegate_addr).unwrap();
- // assert_eq!(6, delegate_addr_updates.len());
- assert_eq!(&stark_felt!(456_u32), delegate_addr_updates.get(&StorageKey(patricia_key!(123_u32))).unwrap());
- assert_eq!(
- &stark_felt!("4e5e39d16e565bacdbc7d8d13b9bc2b51a32c8b2b49062531688dcd2f6ec834"),
- delegate_addr_updates.get(&StorageKey(patricia_key!(300_u32))).unwrap()
- );
- assert_eq!(
- &stark_felt!(1536727068981429685321_u128),
- delegate_addr_updates.get(&StorageKey(patricia_key!(311_u32))).unwrap()
- );
- assert_eq!(&stark_felt!(19_u32), delegate_addr_updates.get(&StorageKey(patricia_key!(322_u32))).unwrap());
- assert_eq!(
- &stark_felt!(TESTING_HASH_0_12_2),
- delegate_addr_updates
- .get(&StorageKey(patricia_key!("2e9111f912ea3746e28b8e693578fdbcc18d64a3380d03bd67c0c04f5715ed1")))
- .unwrap()
- );
- assert_eq!(
- &stark_felt!(2_u8),
- delegate_addr_updates
- .get(&StorageKey(patricia_key!("1cda892019d02a987cdc80f1500179f0e33fbd6cac8cb2ffef5d6d05101a8dc")))
- .unwrap()
- );
+#[fixture]
+pub fn load_output() -> StarknetOsOutput {
+ let buf = fs::read_to_string("tests/common/os_output.json").unwrap();
+ let raw_output: serde_utils::RawOsOutput = serde_json::from_str(&buf).unwrap();
+
+ decode_output(raw_output.0).unwrap()
}
diff --git a/tests/common/os_output.json b/tests/common/os_output.json
new file mode 100644
index 00000000..5b83c024
--- /dev/null
+++ b/tests/common/os_output.json
@@ -0,0 +1,66 @@
+[
+ 125777881657840305468919655792243043894346744037226223335092204105986408733,
+ 2040334332115293258607805604894929469377060974617729443381753056905784954023,
+ 1,
+ 2535437458273622887584459710067137978693525181086955024571735059458497227738,
+ 310876289256536046287137994578069209749202099665831078341805439700916543594,
+ 5,
+ 2006810680437147719782949677362224138923732654511812452693656965873469983890,
+ 85,
+ 2,
+ 12,
+ 34,
+ 6,
+ 85,
+ 1005161437792794307757078281996005783125378987969285529172328835577592343232,
+ 0,
+ 352040181584456735608515580760888541466059565068553383579463728554843487745,
+ 1,
+ 2,
+ 5,
+ 1005161437792794307757078281996005783125378987969285529172328835577592343232,
+ 340282366920938463463374607431768211462,
+ 692694963414257194264020892248745848197431340753065024006875718260869872089,
+ 123,
+ 456,
+ 300,
+ 2215430303710902791540996484823030809971452078551498009603035870583464052788,
+ 311,
+ 1536727068981429685321,
+ 322,
+ 19,
+ 815679926571212018227195848707562322348558067406060931041239273854107494620,
+ 2,
+ 1316419243995606702889870694869183679645676506242823596326912212936248352465,
+ 3262122051170176624039908867798875903980511552421730070376672653403179864416,
+ 2006810680437147719782949677362224138923732654511812452693656965873469983890,
+ 340282366920938463463374607431768211461,
+ 2084524728099985327606460172540572310995923661656859675449923268913980850263,
+ 85,
+ 47,
+ 321,
+ 543,
+ 444,
+ 666,
+ 1715425246256821823855536409958992540846451989567087551676457027799652256186,
+ 100,
+ 1715425246256821823855536409958992540846451989567087551676457027799652256187,
+ 200,
+ 2221633069513894212967173919871301977519426338681819384231748898933664013766,
+ 340282366920938463463374607431768211460,
+ 3262122051170176624039908867798875903980511552421730070376672653403179864416,
+ 15,
+ 1,
+ 111,
+ 987,
+ 555,
+ 888,
+ 666,
+ 999,
+ 2618767603815038378512366346550627731109766804643583016834052353912473402832,
+ 442721857769029238784,
+ 3302098605493938887217934688678356071939708546668669666319008757914002811976,
+ 340282366920938463463374607431768211456,
+ 3262122051170176624039908867798875903980511552421730070376672653403179864416,
+ 0
+]
\ No newline at end of file
diff --git a/tests/common/serde.rs b/tests/common/serde_utils.rs
similarity index 95%
rename from tests/common/serde.rs
rename to tests/common/serde_utils.rs
index e988a02d..55f36569 100644
--- a/tests/common/serde.rs
+++ b/tests/common/serde_utils.rs
@@ -65,3 +65,7 @@ impl StarknetOsInputUtil {
.map_err(|e| SnOsError::CatchAll(format!("{e}")))
}
}
+
+#[serde_as]
+#[derive(Debug, Deserialize)]
+pub struct RawOsOutput(#[serde_as(as = "Vec")] pub Vec);
diff --git a/tests/snos.rs b/tests/snos.rs
index 954ad386..96a71e61 100644
--- a/tests/snos.rs
+++ b/tests/snos.rs
@@ -1,18 +1,22 @@
mod common;
+use blockifier::state::state_api::State;
use blockifier::test_utils::DictStateReader;
use blockifier::transaction::objects::TransactionExecutionInfo;
-use cairo_felt::felt_str;
+use cairo_felt::{felt_str, Felt252};
use common::{
- initial_state, load_input, prepare_os_test, EXPECTED_PREV_ROOT, EXPECTED_UPDATED_ROOT, TESTING_BLOCK_HASH,
+ initial_state, load_input, load_output, prepare_os_test, EXPECTED_PREV_ROOT, EXPECTED_UPDATED_ROOT,
+ TESTING_BLOCK_HASH, TESTING_HASH_0_12_2,
};
-use rstest::*;
-use snos::io::StarknetOsInput;
+use rstest::rstest;
+use snos::io::{StarknetOsInput, StarknetOsOutput};
use snos::state::SharedState;
+use snos::utils::felt_api2vm;
use snos::SnOsRunner;
use starknet_api::block::BlockNumber;
use starknet_api::core::{ContractAddress, PatriciaKey};
use starknet_api::hash::{StarkFelt, StarkHash};
+use starknet_api::state::StorageKey;
use starknet_api::{contract_address, patricia_key, stark_felt};
#[rstest]
@@ -25,6 +29,48 @@ fn snos_run_test(_load_input: &StarknetOsInput, initial_state: SharedState, Vec)) {
let (mut prepare_os_test, _) = prepare_os_test;
+ let diff = prepare_os_test.cache.to_state_diff();
+
+ let addr_1 = contract_address!("46fd0893101585e0c7ebd3caf8097b179f774102d6373760c8f60b1a5ef8c92");
+ let addr_1_updates = diff.storage_updates.get(&addr_1).unwrap();
+ assert_eq!(5, addr_1_updates.len());
+ assert_eq!(&stark_felt!(47_u32), addr_1_updates.get(&StorageKey(patricia_key!(85_u32))).unwrap());
+ assert_eq!(&stark_felt!(543_u32), addr_1_updates.get(&StorageKey(patricia_key!(321_u32))).unwrap());
+ assert_eq!(&stark_felt!(666_u32), addr_1_updates.get(&StorageKey(patricia_key!(444_u32))).unwrap());
+
+ let addr_2 = contract_address!("4e9665675ca1ac12820b7aff2f44fec713e272efcd3f20aa0fd8ca277f25dc6");
+ let addr_2_updates = diff.storage_updates.get(&addr_2).unwrap();
+ assert_eq!(&stark_felt!(1_u32), addr_2_updates.get(&StorageKey(patricia_key!(15_u32))).unwrap());
+ assert_eq!(&stark_felt!(987_u32), addr_2_updates.get(&StorageKey(patricia_key!(111_u32))).unwrap());
+ assert_eq!(&stark_felt!(888_u32), addr_2_updates.get(&StorageKey(patricia_key!(555_u32))).unwrap());
+ assert_eq!(&stark_felt!(999_u32), addr_2_updates.get(&StorageKey(patricia_key!(666_u32))).unwrap());
+
+ let delegate_addr = contract_address!("238e6b5dffc9f0eb2fe476855d0cd1e9e034e5625663c7eda2d871bd4b6eac0");
+ let delegate_addr_updates = diff.storage_updates.get(&delegate_addr).unwrap();
+ // assert_eq!(6, delegate_addr_updates.len());
+ assert_eq!(&stark_felt!(456_u32), delegate_addr_updates.get(&StorageKey(patricia_key!(123_u32))).unwrap());
+ assert_eq!(
+ &stark_felt!("4e5e39d16e565bacdbc7d8d13b9bc2b51a32c8b2b49062531688dcd2f6ec834"),
+ delegate_addr_updates.get(&StorageKey(patricia_key!(300_u32))).unwrap()
+ );
+ assert_eq!(
+ &stark_felt!(1536727068981429685321_u128),
+ delegate_addr_updates.get(&StorageKey(patricia_key!(311_u32))).unwrap()
+ );
+ assert_eq!(&stark_felt!(19_u32), delegate_addr_updates.get(&StorageKey(patricia_key!(322_u32))).unwrap());
+ assert_eq!(
+ &stark_felt!(TESTING_HASH_0_12_2),
+ delegate_addr_updates
+ .get(&StorageKey(patricia_key!("2e9111f912ea3746e28b8e693578fdbcc18d64a3380d03bd67c0c04f5715ed1")))
+ .unwrap()
+ );
+ assert_eq!(
+ &stark_felt!(2_u8),
+ delegate_addr_updates
+ .get(&StorageKey(patricia_key!("1cda892019d02a987cdc80f1500179f0e33fbd6cac8cb2ffef5d6d05101a8dc")))
+ .unwrap()
+ );
+
let _commitment = prepare_os_test.apply_state();
assert_eq!(BlockNumber(2), prepare_os_test.get_block_num());
@@ -49,3 +95,16 @@ fn parse_os_input(load_input: &StarknetOsInput) {
assert_eq!(felt_str!(EXPECTED_UPDATED_ROOT, 16), load_input.contract_state_commitment_info.updated_root);
assert!(!load_input.transactions.is_empty());
}
+
+#[rstest]
+fn parse_os_output(load_input: &StarknetOsInput, load_output: StarknetOsOutput) {
+ assert_eq!(load_input.contract_state_commitment_info.previous_root, load_output.prev_state_root);
+ assert_eq!(load_input.contract_state_commitment_info.updated_root, load_output.new_state_root);
+ assert_eq!(Felt252::from(1), load_output.block_number);
+ assert_eq!(load_input.block_hash, load_output.block_hash);
+ assert_eq!(felt_api2vm(load_input.general_config.starknet_os_config.hash()), load_output.config_hash);
+ assert_eq!(4, load_output.messages_to_l1.len());
+ assert_eq!(4, load_output.messages_to_l2.len());
+ assert_eq!(4, load_output.state_updates.len());
+ assert_eq!(4, load_output.contract_class_diff.len());
+}