From 5cec67a90cea668a6726f366e8588fc2f97fffb6 Mon Sep 17 00:00:00 2001 From: Nimrod Weiss Date: Thu, 27 Feb 2025 18:25:37 +0200 Subject: [PATCH] feat(starknet_os): create panicking cached state --- crates/blockifier/src/state/cached_state.rs | 2 +- .../src/hint_processor/execution_helper.rs | 64 +++++++++++++++++-- crates/starknet_os/src/io/os_input.rs | 15 ++++- crates/starknet_os/src/runner.rs | 11 +++- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/crates/blockifier/src/state/cached_state.rs b/crates/blockifier/src/state/cached_state.rs index 8fd709b17db..21cc7476d88 100644 --- a/crates/blockifier/src/state/cached_state.rs +++ b/crates/blockifier/src/state/cached_state.rs @@ -31,7 +31,7 @@ pub struct CachedState { // Invariant: read/write access is managed by CachedState. // Using interior mutability to update caches during `State`'s immutable getters. pub(crate) cache: RefCell, - pub(crate) class_hash_to_class: RefCell, + pub class_hash_to_class: RefCell, } impl CachedState { diff --git a/crates/starknet_os/src/hint_processor/execution_helper.rs b/crates/starknet_os/src/hint_processor/execution_helper.rs index d882f89b3e8..ec53f7c618b 100644 --- a/crates/starknet_os/src/hint_processor/execution_helper.rs +++ b/crates/starknet_os/src/hint_processor/execution_helper.rs @@ -1,10 +1,15 @@ -use blockifier::state::cached_state::CachedState; +use std::collections::HashMap; + +use blockifier::execution::contract_class::RunnableCompiledClass; +use blockifier::state::cached_state::{CachedState, StateMaps}; use blockifier::state::state_api::StateReader; #[cfg(any(feature = "testing", test))] use blockifier::test_utils::dict_state_reader::DictStateReader; use cairo_vm::types::program::Program; +use starknet_api::contract_class::SierraVersion; -use crate::io::os_input::StarknetOsInput; +use crate::errors::StarknetOsError; +use crate::io::os_input::{CachedStateInput, StarknetOsInput}; /// A helper struct that provides access to the OS state and commitments. pub struct OsExecutionHelper { @@ -14,13 +19,58 @@ pub struct OsExecutionHelper { } impl OsExecutionHelper { - pub fn new(os_input: StarknetOsInput, os_program: Program) -> Self { - Self { cached_state: Self::initialize_cached_state(&os_input), os_input, os_program } + pub fn new( + os_input: StarknetOsInput, + os_program: Program, + state_reader: S, + state_input: CachedStateInput, + ) -> Result { + Ok(Self { + cached_state: Self::initialize_cached_state(state_reader, state_input)?, + os_input, + os_program, + }) } - // TODO(Dori): Create a cached state with all initial read values from the OS input. - fn initialize_cached_state(_os_input: &StarknetOsInput) -> CachedState { - todo!() + fn initialize_cached_state( + state_reader: S, + state_input: CachedStateInput, + ) -> Result, StarknetOsError> { + let mut empty_cached_state = CachedState::new(state_reader); + let mut state_maps = StateMaps::default(); + let mut contract_classes = HashMap::new(); + + // Insert contracts. + for (class_hash, deprecated_class) in state_input.deprecated_compiled_classes.into_iter() { + contract_classes + .insert(class_hash, RunnableCompiledClass::V0(deprecated_class.try_into()?)); + } + for (class_hash, class) in state_input.compiled_classes.into_iter() { + // It doesn't matter which version is used. + let sierra_version = SierraVersion::LATEST; + contract_classes + .insert(class_hash, RunnableCompiledClass::V1((class, sierra_version).try_into()?)); + } + + // Insert storage. + for (contract_address, storage) in state_input.storage.into_iter() { + for (key, value) in storage.into_iter() { + state_maps.storage.insert((contract_address, key), value); + } + } + // Insert nonces. + state_maps.nonces = state_input.address_to_nonce; + + // Insert class hashes. + state_maps.class_hashes = state_input.address_to_class_hash; + + // Insert compiled class hashes. + state_maps.compiled_class_hashes = state_input.class_hash_to_compiled_class_hash; + + // Update the cached state. + empty_cached_state.update_cache(&state_maps, contract_classes); + + Ok(empty_cached_state) } } diff --git a/crates/starknet_os/src/io/os_input.rs b/crates/starknet_os/src/io/os_input.rs index c63c504de92..92f4072e3be 100644 --- a/crates/starknet_os/src/io/os_input.rs +++ b/crates/starknet_os/src/io/os_input.rs @@ -4,9 +4,10 @@ use blockifier::context::ChainInfo; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use shared_execution_objects::central_objects::CentralTransactionExecutionInfo; use starknet_api::block::{BlockHash, BlockInfo, BlockNumber}; -use starknet_api::core::{ClassHash, ContractAddress}; +use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::deprecated_contract_class::ContractClass; use starknet_api::executable_transaction::Transaction; +use starknet_api::state::StorageKey; use starknet_patricia::hash::hash_trait::HashOutput; use starknet_patricia::patricia_merkle_tree::types::SubTreeHeight; use starknet_types_core::felt::Felt; @@ -60,6 +61,7 @@ pub struct StarknetOsInput { _contract_state_commitment_info: CommitmentInfo, pub address_to_storage_commitment_info: HashMap, _contract_class_commitment_info: CommitmentInfo, + // TODO(Nimrod): Remove these two field once they move to `CachedStateInput`. pub deprecated_compiled_classes: HashMap, _compiled_classes: HashMap, pub(crate) chain_info: ChainInfo, @@ -77,3 +79,14 @@ pub struct StarknetOsInput { _debug_mode: bool, pub(crate) full_output: bool, } + +#[derive(Default)] +#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] +pub struct CachedStateInput { + pub(crate) storage: HashMap>, + pub(crate) address_to_class_hash: HashMap, + pub(crate) address_to_nonce: HashMap, + pub(crate) class_hash_to_compiled_class_hash: HashMap, + pub(crate) deprecated_compiled_classes: HashMap, + pub(crate) compiled_classes: HashMap, +} diff --git a/crates/starknet_os/src/runner.rs b/crates/starknet_os/src/runner.rs index 2daf0bbea50..8d75a508321 100644 --- a/crates/starknet_os/src/runner.rs +++ b/crates/starknet_os/src/runner.rs @@ -13,13 +13,14 @@ use crate::hint_processor::snos_hint_processor::{ SnosHintProcessor, SyscallHintProcessor, }; -use crate::io::os_input::StarknetOsInput; +use crate::io::os_input::{CachedStateInput, StarknetOsInput}; use crate::io::os_output::StarknetOsRunnerOutput; pub fn run_os( compiled_os: &[u8], layout: LayoutName, os_input: StarknetOsInput, + state_reader: S, ) -> Result { // Init CairoRunConfig. let cairo_run_config = @@ -40,8 +41,12 @@ pub fn run_os( // Init the Cairo VM. let end = cairo_runner.initialize(allow_missing_builtins)?; + // TODO(Nimrod): Get `cached_state_input` as input. + let cached_state_input = CachedStateInput::default(); + // Create execution helper. - let execution_helper = OsExecutionHelper::::new(os_input, os_program); + let execution_helper = + OsExecutionHelper::new(os_input, os_program, state_reader, cached_state_input)?; // Create syscall handlers. let syscall_handler = SyscallHintProcessor::new(); @@ -79,5 +84,5 @@ pub fn run_os_stateless( layout: LayoutName, os_input: StarknetOsInput, ) -> Result { - run_os::(compiled_os, layout, os_input) + run_os(compiled_os, layout, os_input, PanickingStateReader) }