Skip to content

Commit

Permalink
refactor(katana): execute txs using iterator (#1180)
Browse files Browse the repository at this point in the history
* Execute tx thru iterator

* update
  • Loading branch information
kariy authored Nov 16, 2023
1 parent 2b3efb2 commit 62980bb
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 66 deletions.
4 changes: 2 additions & 2 deletions crates/katana/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ impl Backend {

let mut estimations = Vec::with_capacity(transactions.len());

let results = TransactionExecutor::new(&mut state, &block_context, false)
let results = TransactionExecutor::new(&mut state, &block_context, false, transactions)
.with_error_log()
.execute_many(transactions);
.execute();

for res in results {
let exec_info = res?;
Expand Down
131 changes: 72 additions & 59 deletions crates/katana/core/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,22 @@ impl Default for ExecutionOutcome {
}
}

/// The result of a transaction execution.
pub type TxExecutionResult = Result<TransactionExecutionInfo, TransactionExecutionError>;

/// A transaction executor.
///
/// The transactions will be executed in an iterator fashion, sequentially, in the
/// exact order they are provided to the executor. The execution is done within its implementation
/// of the [`Iterator`] trait.
pub struct TransactionExecutor<'a> {
/// A flag to enable/disable fee charging.
charge_fee: bool,
/// The block context the transactions will be executed on.
block_context: &'a BlockContext,
/// The transactions to be executed (in the exact order they are in the iterator).
transactions: std::vec::IntoIter<Transaction>,
/// The state the transactions will be executed on.
state: &'a mut CachedStateWrapper<StateRefDb>,

// logs flags
Expand All @@ -111,6 +124,7 @@ impl<'a> TransactionExecutor<'a> {
state: &'a mut CachedStateWrapper<StateRefDb>,
block_context: &'a BlockContext,
charge_fee: bool,
transactions: Vec<Transaction>,
) -> Self {
Self {
state,
Expand All @@ -119,6 +133,7 @@ impl<'a> TransactionExecutor<'a> {
error_log: false,
events_log: false,
resources_log: false,
transactions: transactions.into_iter(),
}
}

Expand All @@ -133,78 +148,76 @@ impl<'a> TransactionExecutor<'a> {
pub fn with_resources_log(self) -> Self {
Self { resources_log: true, ..self }
}
}

impl<'a> TransactionExecutor<'a> {
pub fn execute_many(
&mut self,
transactions: Vec<Transaction>,
) -> Vec<Result<TransactionExecutionInfo, TransactionExecutionError>> {
transactions.into_iter().map(|tx| self.execute(tx)).collect()
/// A method to conveniently execute all the transactions and return their results.
pub fn execute(self) -> Vec<TxExecutionResult> {
self.collect()
}
}

pub fn execute(
&mut self,
transaction: Transaction,
) -> Result<TransactionExecutionInfo, TransactionExecutionError> {
let sierra = if let Transaction::Declare(DeclareTransaction {
sierra_class: Some(sierra_class),
inner,
..
}) = &transaction
{
Some((inner.class_hash(), sierra_class.clone()))
} else {
None
};

let res = match transaction.into() {
ExecutionTransaction::AccountTransaction(tx) => {
tx.execute(&mut self.state.inner_mut(), self.block_context, self.charge_fee)
}
ExecutionTransaction::L1HandlerTransaction(tx) => {
tx.execute(&mut self.state.inner_mut(), self.block_context, self.charge_fee)
}
};

match res {
Ok(exec_info) => {
if let Some((class_hash, sierra_class)) = sierra {
self.state
.set_sierra_class(class_hash, sierra_class)
.expect("failed to set sierra class");
impl<'a> Iterator for TransactionExecutor<'a> {
type Item = TxExecutionResult;
fn next(&mut self) -> Option<Self::Item> {
self.transactions.next().map(|tx| {
let sierra = if let Transaction::Declare(DeclareTransaction {
sierra_class: Some(sierra_class),
inner,
..
}) = &tx
{
Some((inner.class_hash(), sierra_class.clone()))
} else {
None
};

let res = match tx.into() {
ExecutionTransaction::AccountTransaction(tx) => {
tx.execute(&mut self.state.inner_mut(), self.block_context, self.charge_fee)
}
ExecutionTransaction::L1HandlerTransaction(tx) => {
tx.execute(&mut self.state.inner_mut(), self.block_context, self.charge_fee)
}
};

match res {
Ok(exec_info) => {
if let Some((class_hash, sierra_class)) = sierra {
self.state
.set_sierra_class(class_hash, sierra_class)
.expect("failed to set sierra class");
}

if self.error_log {
if let Some(err) = &exec_info.revert_error {
let formatted_err = format!("{:?}", err).replace("\\n", "\n");
warn!(target: "executor", "Transaction execution error: {formatted_err}");
if self.error_log {
if let Some(err) = &exec_info.revert_error {
let formatted_err = format!("{:?}", err).replace("\\n", "\n");
warn!(target: "executor", "Transaction execution error: {formatted_err}");
}
}
}

if self.resources_log {
trace!(
target: "executor",
"Transaction resource usage: {}",
pretty_print_resources(&exec_info.actual_resources)
);
}
if self.resources_log {
trace!(
target: "executor",
"Transaction resource usage: {}",
pretty_print_resources(&exec_info.actual_resources)
);
}

if self.events_log {
trace_events(&events_from_exec_info(&exec_info));
}

if self.events_log {
trace_events(&events_from_exec_info(&exec_info));
Ok(exec_info)
}

Ok(exec_info)
}
Err(err) => {
if self.error_log {
warn_message_transaction_error_exec_error(&err);
}

Err(err) => {
if self.error_log {
warn_message_transaction_error_exec_error(&err);
Err(err)
}

Err(err)
}
}
})
}
}

Expand Down
10 changes: 5 additions & 5 deletions crates/katana/core/src/service/block_producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,15 @@ impl IntervalBlockProducer {
&mut state,
&self.backend.env.read().block,
!self.backend.config.read().disable_fee,
transactions.clone(),
)
.with_error_log()
.with_events_log()
.with_resources_log()
.execute_many(transactions.clone())
.into_iter()
.zip(transactions)
.map(|(res, tx)| match res {
Ok(exec_info) => {
let executed_tx = ExecutedTransaction::new(tx, exec_info);
Ok(execution_info) => {
let executed_tx = ExecutedTransaction::new(tx, execution_info);
MaybeInvalidExecutedTransaction::Valid(Arc::new(executed_tx))
}
Err(err) => {
Expand Down Expand Up @@ -354,11 +353,12 @@ impl InstantBlockProducer {
&mut state,
&block_context,
!backend.config.read().disable_fee,
transactions.clone(),
)
.with_error_log()
.with_events_log()
.with_resources_log()
.execute_many(transactions.clone());
.execute();

let outcome = backend
.do_mine_block(create_execution_outcome(
Expand Down

0 comments on commit 62980bb

Please sign in to comment.