diff --git a/crates/blockifier/src/blockifier/transaction_executor.rs b/crates/blockifier/src/blockifier/transaction_executor.rs index 14c13ed932..c9a9c9c569 100644 --- a/crates/blockifier/src/blockifier/transaction_executor.rs +++ b/crates/blockifier/src/blockifier/transaction_executor.rs @@ -12,6 +12,7 @@ use itertools::Itertools; use starknet_api::core::ClassHash; use thiserror::Error; +use crate::blockifier::block::{pre_process_block, BlockNumberHashPair}; use crate::blockifier::config::TransactionExecutorConfig; use crate::bouncer::{Bouncer, BouncerWeights}; #[cfg(feature = "concurrency")] @@ -19,7 +20,7 @@ use crate::concurrency::worker_logic::WorkerExecutor; use crate::context::BlockContext; use crate::state::cached_state::{CachedState, CommitmentStateDiff, TransactionalState}; use crate::state::errors::StateError; -use crate::state::state_api::StateReader; +use crate::state::state_api::{StateReader, StateResult}; use crate::transaction::errors::TransactionExecutionError; use crate::transaction::objects::TransactionExecutionInfo; use crate::transaction::transaction_execution::Transaction; @@ -44,7 +45,7 @@ pub enum TransactionExecutorError { pub type TransactionExecutorResult = Result; pub type VisitedSegmentsMapping = Vec<(ClassHash, Vec)>; -// TODO(Gilad): make this hold TransactionContext instead of BlockContext. +/// A transaction executor, used for building a single block. pub struct TransactionExecutor { pub block_context: BlockContext, pub bouncer: Bouncer, @@ -60,24 +61,37 @@ pub struct TransactionExecutor { } impl TransactionExecutor { + /// Performs pre-processing required for block building before creating the executor. + pub fn pre_process_and_create( + initial_state_reader: S, + block_context: BlockContext, + old_block_number_and_hash: Option, + config: TransactionExecutorConfig, + ) -> StateResult { + let mut block_state = CachedState::new(initial_state_reader); + pre_process_block( + &mut block_state, + old_block_number_and_hash, + block_context.block_info().block_number, + )?; + Ok(Self::new(block_state, block_context, config)) + } + + // TODO(Yoni): consider making this c-tor private. pub fn new( block_state: CachedState, block_context: BlockContext, config: TransactionExecutorConfig, ) -> Self { - log::debug!("Initializing Transaction Executor..."); let bouncer_config = block_context.bouncer_config.clone(); // Note: the state might not be empty even at this point; it is the creator's // responsibility to tune the bouncer according to pre and post block process. - let tx_executor = Self { + Self { block_context, bouncer: Bouncer::new(bouncer_config), config, block_state: Some(block_state), - }; - log::debug!("Initialized Transaction Executor."); - - tx_executor + } } /// Executes the given transaction on the state maintained by the executor. diff --git a/crates/blockifier/src/blockifier/transaction_executor_test.rs b/crates/blockifier/src/blockifier/transaction_executor_test.rs index 7be2bf7ab4..0c293c9635 100644 --- a/crates/blockifier/src/blockifier/transaction_executor_test.rs +++ b/crates/blockifier/src/blockifier/transaction_executor_test.rs @@ -6,6 +6,7 @@ use starknet_api::transaction::{Fee, TransactionVersion}; use starknet_api::{declare_tx_args, deploy_account_tx_args, felt, invoke_tx_args, nonce}; use starknet_types_core::felt::Felt; +use crate::blockifier::block::BlockNumberHashPair; use crate::blockifier::config::TransactionExecutorConfig; use crate::blockifier::transaction_executor::{ TransactionExecutor, @@ -34,15 +35,21 @@ use crate::transaction::test_utils::{ }; use crate::transaction::transaction_execution::Transaction; use crate::transaction::transactions::L1HandlerTransaction; - fn tx_executor_test_body( state: CachedState, block_context: BlockContext, tx: Transaction, expected_bouncer_weights: BouncerWeights, ) { - let mut tx_executor = - TransactionExecutor::new(state, block_context, TransactionExecutorConfig::default()); + let block_number_hash_pair = + BlockNumberHashPair::create_dummy_given_current(block_context.block_info().block_number); + let mut tx_executor = TransactionExecutor::pre_process_and_create( + state, + block_context, + block_number_hash_pair, + TransactionExecutorConfig::default(), + ) + .unwrap(); // TODO(Arni, 30/03/2024): Consider adding a test for the transaction execution info. If A test // should not be added, rename the test to `test_bouncer_info`. // TODO(Arni, 30/03/2024): Test all bouncer weights. diff --git a/crates/blockifier/src/context.rs b/crates/blockifier/src/context.rs index 9e67662b36..58fb49177a 100644 --- a/crates/blockifier/src/context.rs +++ b/crates/blockifier/src/context.rs @@ -17,7 +17,6 @@ use crate::transaction::objects::{ }; use crate::versioned_constants::VersionedConstants; -/// Create via [`crate::blockifier::block::pre_process_block`] to ensure correctness. #[derive(Clone, Debug)] pub struct TransactionContext { pub block_context: BlockContext, diff --git a/crates/blockifier/src/test_utils/struct_impls.rs b/crates/blockifier/src/test_utils/struct_impls.rs index 6d3d21258d..f27cef3f82 100644 --- a/crates/blockifier/src/test_utils/struct_impls.rs +++ b/crates/blockifier/src/test_utils/struct_impls.rs @@ -2,15 +2,17 @@ use std::sync::Arc; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use serde_json::Value; -use starknet_api::block::{BlockNumber, BlockTimestamp}; +use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp}; use starknet_api::core::{ChainId, ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkHash; use starknet_api::transaction::{Calldata, Fee, TransactionHash, TransactionVersion}; use starknet_api::{calldata, contract_address, felt, patricia_key}; use starknet_types_core::felt::Felt; use super::update_json_value; use crate::abi::abi_utils::selector_from_name; -use crate::blockifier::block::{BlockInfo, GasPrices}; +use crate::abi::constants; +use crate::blockifier::block::{BlockInfo, BlockNumberHashPair, GasPrices}; use crate::bouncer::{BouncerConfig, BouncerWeights}; use crate::context::{BlockContext, ChainInfo, FeeTokenAddresses, TransactionContext}; use crate::execution::call_info::{CallExecution, CallInfo, Retdata}; @@ -139,6 +141,18 @@ impl GasCosts { } } +impl BlockNumberHashPair { + pub fn create_dummy_given_current(block_number: BlockNumber) -> Option { + if block_number.0 < constants::STORED_BLOCK_HASH_BUFFER { + return None; + } + Some(Self { + number: BlockNumber(block_number.0 - constants::STORED_BLOCK_HASH_BUFFER), + hash: BlockHash(StarkHash::ONE), + }) + } +} + impl ChainInfo { pub fn create_for_testing() -> Self { Self { diff --git a/crates/native_blockifier/src/py_block_executor.rs b/crates/native_blockifier/src/py_block_executor.rs index 841619756c..ee20c03a67 100644 --- a/crates/native_blockifier/src/py_block_executor.rs +++ b/crates/native_blockifier/src/py_block_executor.rs @@ -1,12 +1,10 @@ use std::collections::HashMap; -use blockifier::blockifier::block::pre_process_block; use blockifier::blockifier::config::TransactionExecutorConfig; use blockifier::blockifier::transaction_executor::{TransactionExecutor, TransactionExecutorError}; use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; use blockifier::execution::call_info::CallInfo; -use blockifier::state::cached_state::CachedState; use blockifier::state::global_cache::GlobalContractCache; use blockifier::transaction::objects::{GasVector, ResourcesMapping, TransactionExecutionInfo}; use blockifier::transaction::transaction_execution::Transaction; @@ -133,18 +131,13 @@ impl PyBlockExecutor { // Create state reader. let papyrus_reader = self.get_aligned_reader(next_block_number); - let mut state = CachedState::new(papyrus_reader); - - pre_process_block( - &mut state, + // Create and set executor. + self.tx_executor = Some(TransactionExecutor::pre_process_and_create( + papyrus_reader, + block_context, into_block_number_hash_pair(old_block_number_and_hash), - next_block_number, - )?; - - let tx_executor = - TransactionExecutor::new(state, block_context, self.tx_executor_config.clone()); - self.tx_executor = Some(tx_executor); - + self.tx_executor_config.clone(), + )?); Ok(()) } diff --git a/crates/papyrus_execution/src/lib.rs b/crates/papyrus_execution/src/lib.rs index 7f796a0e95..d24bf7f4ae 100644 --- a/crates/papyrus_execution/src/lib.rs +++ b/crates/papyrus_execution/src/lib.rs @@ -654,6 +654,7 @@ fn execute_transactions( _ => None, }; let blockifier_tx = to_blockifier_tx(tx, tx_hash, transaction_index)?; + // TODO(Yoni): use the TransactionExecutor instead. let tx_execution_info_result = blockifier_tx.execute(&mut transactional_state, &block_context, charge_fee, validate); let state_diff =