diff --git a/crates/blockifier_reexecution/src/state_reader.rs b/crates/blockifier_reexecution/src/state_reader.rs index 9cf218d9f1..eadb24337f 100644 --- a/crates/blockifier_reexecution/src/state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader.rs @@ -2,6 +2,7 @@ pub mod compile; mod errors; #[cfg(test)] pub mod raw_rpc_json_test; +pub mod reexecution_state_reader; #[cfg(test)] #[cfg(feature = "blockifier_regression_https_testing")] pub mod rpc_https_test; diff --git a/crates/blockifier_reexecution/src/state_reader/errors.rs b/crates/blockifier_reexecution/src/state_reader/errors.rs index e2d5a0c1dc..8d15f1de1c 100644 --- a/crates/blockifier_reexecution/src/state_reader/errors.rs +++ b/crates/blockifier_reexecution/src/state_reader/errors.rs @@ -1,3 +1,4 @@ +use blockifier::execution::errors::ContractClassError; use blockifier::state::errors::StateError; use blockifier::transaction::errors::TransactionExecutionError; use blockifier::versioned_constants::VersionedConstantsError; @@ -21,4 +22,6 @@ pub enum ReexecutionError { TransactionExecutionError(#[from] TransactionExecutionError), #[error(transparent)] VersionedConstants(#[from] VersionedConstantsError), + #[error(transparent)] + ContractClassError(#[from] ContractClassError), } diff --git a/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs b/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs new file mode 100644 index 0000000000..c13ecb7b5f --- /dev/null +++ b/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs @@ -0,0 +1,66 @@ +use blockifier::execution::contract_class::ClassInfo; +use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction; +use papyrus_execution::DEPRECATED_CONTRACT_SIERRA_SIZE; +use starknet_api::core::ClassHash; +use starknet_api::transaction::{Transaction, TransactionHash}; +use starknet_core::types::ContractClass as StarknetContractClass; + +use super::compile::{legacy_to_contract_class_v0, sierra_to_contact_class_v1}; +use crate::state_reader::errors::ReexecutionError; +use crate::state_reader::test_state_reader::ReexecutionResult; + +pub(crate) trait ReexecutionStateReader { + fn get_contract_class(&self, class_hash: ClassHash) + -> ReexecutionResult; + + fn get_class_info(&self, class_hash: ClassHash) -> ReexecutionResult { + match self.get_contract_class(class_hash)? { + StarknetContractClass::Sierra(sierra) => { + let abi_length = sierra.abi.len(); + let sierra_length = sierra.sierra_program.len(); + Ok(ClassInfo::new(&sierra_to_contact_class_v1(sierra)?, sierra_length, abi_length)?) + } + StarknetContractClass::Legacy(legacy) => { + let abi_length = + legacy.abi.clone().expect("legendary contract should have abi").len(); + Ok(ClassInfo::new( + &legacy_to_contract_class_v0(legacy)?, + DEPRECATED_CONTRACT_SIERRA_SIZE, + abi_length, + )?) + } + } + } + + // TODO(Aner): extend/refactor to accomodate all types of transactions. + fn api_txs_to_blockifier_txs( + &self, + txs_and_hashes: Vec<(Transaction, TransactionHash)>, + ) -> ReexecutionResult> { + txs_and_hashes + .into_iter() + .map(|(tx, tx_hash)| match tx { + Transaction::Invoke(_) | Transaction::DeployAccount(_) => { + BlockifierTransaction::from_api(tx, tx_hash, None, None, None, false) + .map_err(ReexecutionError::from) + } + Transaction::Declare(ref declare_tx) => { + let class_info = self + .get_class_info(declare_tx.class_hash()) + .map_err(ReexecutionError::from)?; + BlockifierTransaction::from_api( + tx, + tx_hash, + Some(class_info), + None, + None, + false, + ) + .map_err(ReexecutionError::from) + } + Transaction::L1Handler(_) => todo!("Implement L1Handler transaction converter"), + Transaction::Deploy(_) => todo!("Implement Deploy transaction converter"), + }) + .collect::, _>>() + } +} diff --git a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs index 51ef7a5129..a94a818bfb 100644 --- a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs +++ b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs @@ -15,6 +15,7 @@ use starknet_api::transaction::{ use starknet_core::types::ContractClass::{Legacy, Sierra}; use crate::state_reader::compile::legacy_to_contract_class_v0; +use crate::state_reader::reexecution_state_reader::ReexecutionStateReader; use crate::state_reader::test_state_reader::{ConsecutiveTestStateReaders, TestStateReader}; const EXAMPLE_INVOKE_TX_HASH: &str = @@ -180,3 +181,12 @@ pub fn test_get_declare_tx_by_hash( pub fn test_get_statediff_rpc(test_state_reader: TestStateReader) { assert!(test_state_reader.get_state_diff().is_ok()); } + +#[rstest] +#[case(EXAMPLE_DECLARE_V1_BLOCK_NUMBER)] +#[case(EXAMPLE_DECLARE_V2_BLOCK_NUMBER)] +#[case(EXAMPLE_DECLARE_V3_BLOCK_NUMBER)] +pub fn test_get_all_blockifier_tx_in_block(#[case] block_number: u64) { + let state_reader = TestStateReader::new_for_testing(BlockNumber(block_number)); + state_reader.api_txs_to_blockifier_txs(state_reader.get_all_txs_in_block().unwrap()).unwrap(); +} diff --git a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs index 6c30e7321d..f871e3c735 100644 --- a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs @@ -15,7 +15,6 @@ use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; use starknet_api::transaction::{Transaction, TransactionHash}; use starknet_core::types::ContractClass as StarknetContractClass; -use starknet_core::types::ContractClass::{Legacy, Sierra}; use starknet_gateway::config::RpcStateReaderConfig; use starknet_gateway::errors::serde_err_to_state_err; use starknet_gateway::rpc_objects::{BlockHeader, GetBlockWithTxHashesParams, ResourcePrice}; @@ -24,6 +23,7 @@ use starknet_types_core::felt::Felt; use crate::state_reader::compile::{legacy_to_contract_class_v0, sierra_to_contact_class_v1}; use crate::state_reader::errors::ReexecutionError; +use crate::state_reader::reexecution_state_reader::ReexecutionStateReader; use crate::state_reader::serde_utils::{ deserialize_transaction_json_to_starknet_api_tx, hashmap_from_raw, @@ -31,7 +31,6 @@ use crate::state_reader::serde_utils::{ }; use crate::state_reader::utils::{ disjoint_hashmap_union, - from_api_txs_to_blockifier_txs, get_chain_info, get_rpc_state_reader_config, }; @@ -64,8 +63,8 @@ impl StateReader for TestStateReader { class_hash: ClassHash, ) -> StateResult { match self.get_contract_class(&class_hash)? { - Sierra(sierra) => sierra_to_contact_class_v1(sierra), - Legacy(legacy) => legacy_to_contract_class_v0(legacy), + StarknetContractClass::Sierra(sierra) => sierra_to_contact_class_v1(sierra), + StarknetContractClass::Legacy(legacy) => legacy_to_contract_class_v0(legacy), } } @@ -231,6 +230,22 @@ impl TestStateReader { } } +impl ReexecutionStateReader for TestStateReader { + fn get_contract_class( + &self, + class_hash: ClassHash, + ) -> ReexecutionResult { + let params = json!({ + "block_id": self.0.block_id, + "class_hash": class_hash.0.to_string(), + }); + let contract_class: StarknetContractClass = + serde_json::from_value(self.0.send_rpc_request("starknet_getClass", params.clone())?) + .map_err(serde_err_to_state_err)?; + Ok(contract_class) + } +} + /// Trait of the functions \ queries required for reexecution. pub trait ConsecutiveStateReaders { fn get_transaction_executor( @@ -276,7 +291,8 @@ impl ConsecutiveStateReaders for ConsecutiveTestStateReaders { } fn get_next_block_txs(&self) -> ReexecutionResult> { - from_api_txs_to_blockifier_txs(self.next_block_state_reader.get_all_txs_in_block()?) + self.next_block_state_reader + .api_txs_to_blockifier_txs(self.next_block_state_reader.get_all_txs_in_block()?) } fn get_next_block_state_diff(&self) -> ReexecutionResult { diff --git a/crates/blockifier_reexecution/src/state_reader/utils.rs b/crates/blockifier_reexecution/src/state_reader/utils.rs index f2fdf593f8..d24876c879 100644 --- a/crates/blockifier_reexecution/src/state_reader/utils.rs +++ b/crates/blockifier_reexecution/src/state_reader/utils.rs @@ -2,18 +2,15 @@ use std::collections::HashMap; use blockifier::context::{ChainInfo, FeeTokenAddresses}; use blockifier::state::cached_state::StateMaps; -use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction; use indexmap::IndexMap; use papyrus_execution::{eth_fee_contract_address, strk_fee_contract_address}; use serde::{Deserialize, Serialize}; use starknet_api::core::{ChainId, ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; -use starknet_api::transaction::{Transaction, TransactionHash}; use starknet_gateway::config::RpcStateReaderConfig; use starknet_types_core::felt::Felt; use super::errors::ReexecutionError; -use crate::state_reader::test_state_reader::ReexecutionResult; pub const RPC_NODE_URL: &str = "https://free-rpc.nethermind.io/mainnet-juno/"; pub const JSON_RPC_VERSION: &str = "2.0"; @@ -39,21 +36,6 @@ pub fn get_chain_info() -> ChainInfo { ChainInfo { chain_id: ChainId::Mainnet, fee_token_addresses: get_fee_token_addresses() } } -// TODO(Aner): extend/refactor to accomodate all types of transactions. -#[allow(dead_code)] -pub(crate) fn from_api_txs_to_blockifier_txs( - txs_and_hashes: Vec<(Transaction, TransactionHash)>, -) -> ReexecutionResult> { - Ok(txs_and_hashes - .into_iter() - .map(|(tx, tx_hash)| match tx { - Transaction::Invoke(_) => { - BlockifierTransaction::from_api(tx, tx_hash, None, None, None, false) - } - _ => unimplemented!(), - }) - .collect::>()?) -} // TODO(Aner): import the following functions instead, to reduce code duplication. pub(crate) fn disjoint_hashmap_union( map1: IndexMap, diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs index 60305adc9f..7314e50205 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -419,7 +419,8 @@ pub type AbiSize = usize; /// The size of the sierra program. pub type SierraSize = usize; -const DEPRECATED_CONTRACT_SIERRA_SIZE: SierraSize = 0; +/// The size of the sierra program for deprecated contracts. +pub const DEPRECATED_CONTRACT_SIERRA_SIZE: SierraSize = 0; /// The transaction input to be executed. // TODO(yair): This should use broadcasted transactions instead of regular transactions, but the