Skip to content

Commit

Permalink
Add execution flags in TransactionExceutor's execute logic
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy committed Sep 25, 2024
1 parent 290338e commit dd69217
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 27 deletions.
17 changes: 12 additions & 5 deletions crates/blockifier/src/blockifier/stateful_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,21 @@ impl<S: StateReader> StatefulValidator<S> {
skip_validate: bool,
skip_fee_check: bool,
) -> StatefulValidatorResult<()> {
let validate = !skip_validate;
let fee_check = !skip_fee_check;

// Deploy account transactions should be fully executed, since the constructor must run
// before `__validate_deploy__`. The execution already includes all necessary validations,
// so they are skipped here.
if let AccountTransaction::DeployAccount(_) = tx {
self.execute(tx)?;
self.execute(tx, validate, fee_check)?;
return Ok(());
}

let tx_context = self.tx_executor.block_context.to_tx_context(&tx);
let fee_check = !skip_fee_check;
self.perform_pre_validation_stage(&tx, &tx_context, fee_check)?;

if !skip_validate {
if validate {
// `__validate__` call.
let versioned_constants = &tx_context.block_context.versioned_constants();
let (_optional_call_info, actual_cost) =
Expand All @@ -109,8 +111,13 @@ impl<S: StateReader> StatefulValidator<S> {
Ok(())
}

fn execute(&mut self, tx: AccountTransaction) -> StatefulValidatorResult<()> {
self.tx_executor.execute(&Transaction::AccountTransaction(tx))?;
fn execute(
&mut self,
tx: AccountTransaction,
validate: bool,
fee_check: bool,
) -> StatefulValidatorResult<()> {
self.tx_executor.execute(&Transaction::AccountTransaction(tx), validate, fee_check)?;
Ok(())
}

Expand Down
19 changes: 11 additions & 8 deletions crates/blockifier/src/blockifier/transaction_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,16 @@ impl<S: StateReader> TransactionExecutor<S> {
pub fn execute(
&mut self,
tx: &Transaction,
validate: bool,
charge_fee: bool,
) -> TransactionExecutorResult<TransactionExecutionInfo> {
let mut transactional_state = TransactionalState::create_transactional(
self.block_state.as_mut().expect(BLOCK_STATE_ACCESS_ERR),
);
// Executing a single transaction cannot be done in a concurrent mode.
let execution_flags = ExecutionFlags {
charge_fee: true,
validate: true,
nonce_check: true,
concurrency_mode: false,
};
let execution_flags =
ExecutionFlags { charge_fee, validate, nonce_check: true, concurrency_mode: false };

let tx_execution_result =
tx.execute_raw(&mut transactional_state, &self.block_context, execution_flags);
match tx_execution_result {
Expand All @@ -122,10 +121,12 @@ impl<S: StateReader> TransactionExecutor<S> {
pub fn execute_txs_sequentially(
&mut self,
txs: &[Transaction],
validate: bool,
charge_fee: bool,
) -> Vec<TransactionExecutorResult<TransactionExecutionInfo>> {
let mut results = Vec::new();
for tx in txs {
match self.execute(tx) {
match self.execute(tx, validate, charge_fee) {
Ok(tx_execution_info) => results.push(Ok(tx_execution_info)),
Err(TransactionExecutorError::BlockFull) => break,
Err(error) => results.push(Err(error)),
Expand Down Expand Up @@ -183,10 +184,12 @@ impl<S: StateReader + Send + Sync> TransactionExecutor<S> {
pub fn execute_txs(
&mut self,
txs: &[Transaction],
validate: bool,
charge_fee: bool,
) -> Vec<TransactionExecutorResult<TransactionExecutionInfo>> {
if !self.config.concurrency_config.enabled {
log::debug!("Executing transactions sequentially.");
self.execute_txs_sequentially(txs)
self.execute_txs_sequentially(txs, validate, charge_fee)
} else {
log::debug!("Executing transactions concurrently.");
let chunk_size = self.config.concurrency_config.chunk_size;
Expand Down
24 changes: 14 additions & 10 deletions crates/blockifier/src/blockifier/transaction_executor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn tx_executor_test_body<S: StateReader>(
// 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.
let _tx_execution_info = tx_executor.execute(&tx).unwrap();
let _tx_execution_info = tx_executor.execute(&tx, true, true).unwrap();
let bouncer_weights = tx_executor.bouncer.get_accumulated_weights();
assert_eq!(bouncer_weights.state_diff_size, expected_bouncer_weights.state_diff_size);
assert_eq!(
Expand Down Expand Up @@ -256,12 +256,16 @@ fn test_bouncing(#[case] initial_bouncer_weights: BouncerWeights, #[case] n_even
tx_executor.bouncer.set_accumulated_weights(initial_bouncer_weights);

tx_executor
.execute(&Transaction::AccountTransaction(emit_n_events_tx(
n_events,
account_address,
contract_address,
nonce_manager.next(account_address),
)))
.execute(
&Transaction::AccountTransaction(emit_n_events_tx(
n_events,
account_address,
contract_address,
nonce_manager.next(account_address),
)),
true,
true,
)
.map_err(|error| panic!("{error:?}: {error}"))
.unwrap();
}
Expand Down Expand Up @@ -297,7 +301,7 @@ fn test_execute_txs_bouncing() {
.collect();

// Run.
let results = tx_executor.execute_txs(&txs);
let results = tx_executor.execute_txs(&txs, true, true);

// Check execution results.
let expected_offset = 3;
Expand Down Expand Up @@ -325,12 +329,12 @@ fn test_execute_txs_bouncing() {

// Check idempotency: excess transactions should not be added.
let remaining_txs = &txs[expected_offset..];
let remaining_tx_results = tx_executor.execute_txs(remaining_txs);
let remaining_tx_results = tx_executor.execute_txs(remaining_txs, true, true);
assert_eq!(remaining_tx_results.len(), 0);

// Reset the bouncer and add the remaining transactions.
tx_executor.bouncer = Bouncer::new(tx_executor.block_context.bouncer_config.clone());
let remaining_tx_results = tx_executor.execute_txs(remaining_txs);
let remaining_tx_results = tx_executor.execute_txs(remaining_txs, true, true);

assert_eq!(remaining_tx_results.len(), 2);
assert!(remaining_tx_results[0].is_ok());
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/test_utils/transfers_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ impl TransfersGenerator {
let account_tx = self.generate_transfer(sender_address, recipient_address);
txs.push(Transaction::AccountTransaction(account_tx));
}
let results = self.executor.execute_txs(&txs);
let results = self.executor.execute_txs(&txs, true, true);
assert_eq!(results.len(), self.config.n_txs);
for result in results {
assert!(!result.unwrap().is_reverted());
Expand Down
7 changes: 4 additions & 3 deletions crates/native_blockifier/src/py_block_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl PyBlockExecutor {
optional_py_class_info: Option<PyClassInfo>,
) -> NativeBlockifierResult<Py<PyBytes>> {
let tx: Transaction = py_tx(tx, optional_py_class_info).expect(PY_TX_PARSING_ERR);
let tx_execution_info = self.tx_executor().execute(&tx)?;
let tx_execution_info = self.tx_executor().execute(&tx, true, true)?;
let thin_tx_execution_info = ThinTransactionExecutionInfo::from_tx_execution_info(
&self.tx_executor().block_context,
tx_execution_info,
Expand Down Expand Up @@ -194,8 +194,9 @@ impl PyBlockExecutor {
.collect();

// Run.
let results =
Python::with_gil(|py| py.allow_threads(|| self.tx_executor().execute_txs(&txs)));
let results = Python::with_gil(|py| {
py.allow_threads(|| self.tx_executor().execute_txs(&txs, true, true))
});

// Process results.
// TODO(Yoni, 15/5/2024): serialize concurrently.
Expand Down

0 comments on commit dd69217

Please sign in to comment.