Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/blockifier_reexecution/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use apollo_gateway::errors::RPCStateReaderError;
use blockifier::blockifier::transaction_executor::TransactionExecutorError;
use blockifier::blockifier_versioned_constants::VersionedConstantsError;
use blockifier::state::errors::StateError;
use blockifier::transaction::errors::TransactionExecutionError;
Expand All @@ -20,6 +21,8 @@ pub enum ReexecutionError {
#[error(transparent)]
State(#[from] StateError),
#[error(transparent)]
TransactionExecutorError(#[from] TransactionExecutorError),
#[error(transparent)]
TransactionExecutionError(#[from] TransactionExecutionError),
#[error(transparent)]
VersionedConstants(#[from] VersionedConstantsError),
Expand Down
46 changes: 45 additions & 1 deletion crates/blockifier_reexecution/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
pub mod cli;
pub mod compile;
mod errors;
pub mod errors;
pub mod serde_utils;
pub mod state_reader;
pub mod utils;

use apollo_gateway_config::config::RpcStateReaderConfig;
use blockifier::blockifier::config::ContractClassManagerConfig;
use blockifier::blockifier::transaction_executor::TransactionExecutionOutput;
use blockifier::context::BlockContext;
use blockifier::state::cached_state::StateMaps;
use blockifier::state::contract_class_manager::ContractClassManager;
use errors::ReexecutionResult;
use starknet_api::block::BlockNumber;
use starknet_api::core::ChainId;
use starknet_api::transaction::Transaction;
use state_reader::rpc_state_reader::ConsecutiveRpcStateReaders;

/// Executes a single transaction at the given block number using the RPC state reader.
pub fn execute_single_transaction(
block_number: BlockNumber,
node_url: String,
chain_id: ChainId,
tx: Transaction,
) -> ReexecutionResult<(TransactionExecutionOutput, StateMaps, BlockContext)> {
let rpc_state_reader_config = RpcStateReaderConfig::from_url(node_url);

// Initialize the contract class manager.
let mut contract_class_manager_config = ContractClassManagerConfig::default();
if cfg!(feature = "cairo_native") {
contract_class_manager_config.cairo_native_run_config.wait_on_native_compilation = true;
contract_class_manager_config.cairo_native_run_config.run_cairo_native = true;
}
let contract_class_manager = ContractClassManager::start(contract_class_manager_config);

// ConsecutiveRpcStateReaders expects the last constructed block number (previous block).
assert!(block_number.0 != 0, "Cannot execute transaction at block 0");
let prev_block_number = BlockNumber(block_number.0 - 1);

let readers = ConsecutiveRpcStateReaders::new(
prev_block_number,
Some(rpc_state_reader_config),
chain_id,
false,
contract_class_manager,
);

readers.execute_single_api_tx(tx)
}
49 changes: 32 additions & 17 deletions crates/blockifier_reexecution/src/state_reader/rpc_state_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ use apollo_gateway_config::config::RpcStateReaderConfig;
use assert_matches::assert_matches;
use blockifier::abi::constants;
use blockifier::blockifier::config::TransactionExecutorConfig;
use blockifier::blockifier::transaction_executor::TransactionExecutor;
use blockifier::blockifier::transaction_executor::{
TransactionExecutionOutput,
TransactionExecutor,
};
use blockifier::blockifier_versioned_constants::VersionedConstants;
use blockifier::bouncer::BouncerConfig;
use blockifier::context::BlockContext;
use blockifier::execution::contract_class::RunnableCompiledClass;
use blockifier::state::cached_state::CommitmentStateDiff;
use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps};
use blockifier::state::contract_class_manager::ContractClassManager;
use blockifier::state::errors::StateError;
use blockifier::state::global_cache::CompiledClasses;
Expand Down Expand Up @@ -475,11 +478,36 @@ impl ConsecutiveRpcStateReaders {
))
}

/// Executes a single transaction.
/// Returns the execution output, initial reads and the block context.
pub fn execute_single_api_tx(
self,
tx: Transaction,
) -> ReexecutionResult<(TransactionExecutionOutput, StateMaps, BlockContext)> {
let chain_id = self.next_block_state_reader.chain_id.clone();
let transaction_hash = tx.calculate_transaction_hash(&chain_id)?;

let blockifier_txs = self
.next_block_state_reader
.api_txs_to_blockifier_txs_next_block(vec![(tx, transaction_hash)])?;
let blockifier_tx = blockifier_txs
.first()
.expect("API to Blockifier transaction conversion returned empty list");

let mut transaction_executor = self.pre_process_and_create_executor(None)?;
let block_context = transaction_executor.block_context.as_ref().clone();

let (tx_execution_info, state_diff) = transaction_executor.execute(blockifier_tx)?;
let initial_reads =
transaction_executor.block_state.as_ref().unwrap().get_initial_reads()?;
Ok(((tx_execution_info, state_diff), initial_reads, block_context))
}

/// Executes a single transaction from a JSON file or given a transaction hash, using RPC to
/// fetch block context. Does not assert correctness, only prints the execution result.
pub fn execute_single_transaction(self, tx_input: TransactionInput) -> ReexecutionResult<()> {
// Get transaction and hash based on input method.
let (transaction, transaction_hash) = match tx_input {
let (transaction, _) = match tx_input {
TransactionInput::FromHash { tx_hash } => {
// Fetch transaction from the next block (the block containing the transaction to
// execute).
Expand All @@ -503,20 +531,7 @@ impl ConsecutiveRpcStateReaders {
}
};

// Convert transaction to BlockifierTransaction using api_txs_to_blockifier_txs_next_block.
let blockifier_tx = self
.next_block_state_reader
.api_txs_to_blockifier_txs_next_block(vec![(transaction, transaction_hash)])?;

// Create transaction executor.
let mut transaction_executor = self.pre_process_and_create_executor(None)?;

// Execute transaction (should be single element).
let execution_results = transaction_executor.execute_txs(&blockifier_tx, None);

// We expect exactly one execution result since we executed a single transaction.
let res =
execution_results.first().expect("Expected exactly one execution result, but got none");
let (res, _, _) = self.execute_single_api_tx(transaction)?;

println!("Execution result: {:?}", res);

Expand Down