Skip to content

Commit 9464fdf

Browse files
blockifier_reexecution: split execute tx logic
1 parent e2a8b50 commit 9464fdf

File tree

3 files changed

+80
-18
lines changed

3 files changed

+80
-18
lines changed

crates/blockifier_reexecution/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use apollo_gateway::errors::RPCStateReaderError;
2+
use blockifier::blockifier::transaction_executor::TransactionExecutorError;
23
use blockifier::blockifier_versioned_constants::VersionedConstantsError;
34
use blockifier::state::errors::StateError;
45
use blockifier::transaction::errors::TransactionExecutionError;
@@ -20,6 +21,8 @@ pub enum ReexecutionError {
2021
#[error(transparent)]
2122
State(#[from] StateError),
2223
#[error(transparent)]
24+
TransactionExecutorError(#[from] TransactionExecutorError),
25+
#[error(transparent)]
2326
TransactionExecutionError(#[from] TransactionExecutionError),
2427
#[error(transparent)]
2528
VersionedConstants(#[from] VersionedConstantsError),
Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,50 @@
11
pub mod cli;
22
pub mod compile;
3-
mod errors;
3+
pub mod errors;
44
pub mod serde_utils;
55
pub mod state_reader;
66
pub mod utils;
7+
8+
use apollo_gateway_config::config::RpcStateReaderConfig;
9+
use blockifier::blockifier::config::ContractClassManagerConfig;
10+
use blockifier::blockifier::transaction_executor::TransactionExecutionOutput;
11+
use blockifier::context::BlockContext;
12+
use blockifier::state::cached_state::StateMaps;
13+
use blockifier::state::contract_class_manager::ContractClassManager;
14+
use errors::ReexecutionResult;
15+
use starknet_api::block::BlockNumber;
16+
use starknet_api::core::ChainId;
17+
use starknet_api::transaction::Transaction;
18+
use state_reader::rpc_state_reader::ConsecutiveRpcStateReaders;
19+
20+
/// Executes a single transaction at the given block number using the RPC state reader.
21+
pub fn execute_single_transaction(
22+
block_number: BlockNumber,
23+
node_url: String,
24+
chain_id: ChainId,
25+
tx: Transaction,
26+
) -> ReexecutionResult<(TransactionExecutionOutput, StateMaps, BlockContext)> {
27+
let rpc_state_reader_config = RpcStateReaderConfig::from_url(node_url);
28+
29+
// Initialize the contract class manager.
30+
let mut contract_class_manager_config = ContractClassManagerConfig::default();
31+
if cfg!(feature = "cairo_native") {
32+
contract_class_manager_config.cairo_native_run_config.wait_on_native_compilation = true;
33+
contract_class_manager_config.cairo_native_run_config.run_cairo_native = true;
34+
}
35+
let contract_class_manager = ContractClassManager::start(contract_class_manager_config);
36+
37+
// ConsecutiveRpcStateReaders expects the last constructed block number (previous block).
38+
assert!(block_number.0 != 0, "Cannot execute transaction at block 0");
39+
let prev_block_number = BlockNumber(block_number.0 - 1);
40+
41+
let readers = ConsecutiveRpcStateReaders::new(
42+
prev_block_number,
43+
Some(rpc_state_reader_config),
44+
chain_id,
45+
false,
46+
contract_class_manager,
47+
);
48+
49+
readers.execute_single_api_tx(tx)
50+
}

crates/blockifier_reexecution/src/state_reader/rpc_state_reader.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ use apollo_gateway_config::config::RpcStateReaderConfig;
99
use assert_matches::assert_matches;
1010
use blockifier::abi::constants;
1111
use blockifier::blockifier::config::TransactionExecutorConfig;
12-
use blockifier::blockifier::transaction_executor::TransactionExecutor;
12+
use blockifier::blockifier::transaction_executor::{
13+
TransactionExecutionOutput,
14+
TransactionExecutor,
15+
};
1316
use blockifier::blockifier_versioned_constants::VersionedConstants;
1417
use blockifier::bouncer::BouncerConfig;
1518
use blockifier::context::BlockContext;
1619
use blockifier::execution::contract_class::RunnableCompiledClass;
17-
use blockifier::state::cached_state::CommitmentStateDiff;
20+
use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps};
1821
use blockifier::state::contract_class_manager::ContractClassManager;
1922
use blockifier::state::errors::StateError;
2023
use blockifier::state::global_cache::CompiledClasses;
@@ -475,11 +478,36 @@ impl ConsecutiveRpcStateReaders {
475478
))
476479
}
477480

481+
/// Executes a single transaction.
482+
/// Returns the execution output, initial reads and the block context.
483+
pub fn execute_single_api_tx(
484+
self,
485+
tx: Transaction,
486+
) -> ReexecutionResult<(TransactionExecutionOutput, StateMaps, BlockContext)> {
487+
let chain_id = self.next_block_state_reader.chain_id.clone();
488+
let transaction_hash = tx.calculate_transaction_hash(&chain_id)?;
489+
490+
let blockifier_txs = self
491+
.next_block_state_reader
492+
.api_txs_to_blockifier_txs_next_block(vec![(tx, transaction_hash)])?;
493+
let blockifier_tx = blockifier_txs
494+
.first()
495+
.expect("API to Blockifier transaction conversion returned empty list");
496+
497+
let mut transaction_executor = self.pre_process_and_create_executor(None)?;
498+
let block_context = transaction_executor.block_context.as_ref().clone();
499+
500+
let (tx_execution_info, state_diff) = transaction_executor.execute(blockifier_tx)?;
501+
let initial_reads =
502+
transaction_executor.block_state.as_ref().unwrap().get_initial_reads()?;
503+
Ok(((tx_execution_info, state_diff), initial_reads, block_context))
504+
}
505+
478506
/// Executes a single transaction from a JSON file or given a transaction hash, using RPC to
479507
/// fetch block context. Does not assert correctness, only prints the execution result.
480508
pub fn execute_single_transaction(self, tx_input: TransactionInput) -> ReexecutionResult<()> {
481509
// Get transaction and hash based on input method.
482-
let (transaction, transaction_hash) = match tx_input {
510+
let (transaction, _) = match tx_input {
483511
TransactionInput::FromHash { tx_hash } => {
484512
// Fetch transaction from the next block (the block containing the transaction to
485513
// execute).
@@ -503,20 +531,7 @@ impl ConsecutiveRpcStateReaders {
503531
}
504532
};
505533

506-
// Convert transaction to BlockifierTransaction using api_txs_to_blockifier_txs_next_block.
507-
let blockifier_tx = self
508-
.next_block_state_reader
509-
.api_txs_to_blockifier_txs_next_block(vec![(transaction, transaction_hash)])?;
510-
511-
// Create transaction executor.
512-
let mut transaction_executor = self.pre_process_and_create_executor(None)?;
513-
514-
// Execute transaction (should be single element).
515-
let execution_results = transaction_executor.execute_txs(&blockifier_tx, None);
516-
517-
// We expect exactly one execution result since we executed a single transaction.
518-
let res =
519-
execution_results.first().expect("Expected exactly one execution result, but got none");
534+
let (res, _, _) = self.execute_single_api_tx(transaction)?;
520535

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

0 commit comments

Comments
 (0)