Skip to content

Commit

Permalink
single unit execution function
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy committed May 16, 2024
1 parent 1b3c1d6 commit 20f2bee
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 86 deletions.
73 changes: 27 additions & 46 deletions crates/katana/executor/src/implementation/blockifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use blockifier::block::{BlockInfo, GasPrices};
use blockifier::context::BlockContext;
use blockifier::state::cached_state::{self, GlobalContractCache, MutRefState};
use blockifier::state::state_api::StateReader;
use blockifier::transaction::objects::TransactionExecutionInfo;
use katana_primitives::block::{ExecutableBlock, GasPrices as KatanaGasPrices, PartialHeader};
use katana_primitives::env::{BlockEnv, CfgEnv};
use katana_primitives::fee::TxFeeInfo;
Expand All @@ -19,7 +18,6 @@ use starknet_api::block::{BlockNumber, BlockTimestamp};
use tracing::info;

use self::state::CachedState;
use crate::utils::build_receipt;
use crate::{
BlockExecutor, EntryPointCall, ExecutionError, ExecutionOutput, ExecutionResult,
ExecutionStats, ExecutorExt, ExecutorFactory, ExecutorResult, ResultAndStates, SimulationFlag,
Expand Down Expand Up @@ -136,10 +134,7 @@ impl<'a> StarknetVMProcessor<'a> {
mut op: F,
) -> Vec<T>
where
F: FnMut(
&mut dyn StateReader,
(TxWithHash, Result<(TransactionExecutionInfo, TxFeeInfo), ExecutionError>),
) -> T,
F: FnMut(&mut dyn StateReader, (TxWithHash, ExecutionResult)) -> T,
{
let block_context = &self.block_context;
let state = &mut self.state.0.write().inner;
Expand All @@ -151,7 +146,7 @@ impl<'a> StarknetVMProcessor<'a> {
let mut results = Vec::with_capacity(transactions.len());
for exec_tx in transactions {
let tx = TxWithHash::from(&exec_tx);
let res = utils::transact(exec_tx, &mut state, block_context, flags);
let res = utils::transact(&mut state, block_context, flags, exec_tx);
results.push(op(&mut state, (tx, res)));
}

Expand Down Expand Up @@ -184,36 +179,29 @@ impl<'a> BlockExecutor<'a> for StarknetVMProcessor<'a> {
};

let tx = TxWithHash::from(&exec_tx);
let res = match utils::transact(exec_tx, &mut state.inner, block_context, flags) {
Ok((info, fee)) => {
// get the trace and receipt from the execution info
let trace = utils::to_exec_info(info);
let receipt = build_receipt(&tx, fee, &trace);

crate::utils::log_resources(&trace.actual_resources);
crate::utils::log_events(receipt.events());
let res = utils::transact(&mut state.inner, block_context, flags, exec_tx);

match &res {
ExecutionResult::Success { receipt, trace } => {
self.stats.l1_gas_used += receipt.fee().gas_consumed;
self.stats.cairo_steps_used += receipt.resources_used().steps as u128;

if let Some(reason) = receipt.revert_reason() {
info!(target: LOG_TARGET, reason = %reason, "Transaction reverted.");
info!(target: LOG_TARGET, %reason, "Transaction reverted.");
}

ExecutionResult::new_success(receipt, trace)
}
Err(e) => {
info!(target: LOG_TARGET, error = %e, "Executing transaction.");
ExecutionResult::new_failed(e)
if let Some((class_hash, compiled, sierra)) = class_decl_artifacts {
state.declared_classes.insert(class_hash, (compiled, sierra));
}

crate::utils::log_resources(&trace.actual_resources);
crate::utils::log_events(&receipt.events());
}
};

// if the tx succeed, inserts the class artifacts into the contract class cache
if res.is_success() {
if let Some((class_hash, compiled, sierra)) = class_decl_artifacts {
state.declared_classes.insert(class_hash, (compiled, sierra));
ExecutionResult::Failed { error } => {
info!(target: LOG_TARGET, %error, "Executing transaction.");
}
}
};

self.transactions.push((tx, res));
}
Expand Down Expand Up @@ -258,17 +246,9 @@ impl ExecutorExt for StarknetVMProcessor<'_> {
transactions: Vec<ExecutableTxWithHash>,
flags: SimulationFlag,
) -> Vec<ResultAndStates> {
self.simulate_with(transactions, &flags, |_, (tx, res)| {
let result = match res {
Ok((info, fee)) => {
let trace = utils::to_exec_info(info);
let receipt = build_receipt(&tx, fee, &trace);
ExecutionResult::new_success(receipt, trace)
}
Err(e) => ExecutionResult::new_failed(e),
};

ResultAndStates { result, states: Default::default() }
self.simulate_with(transactions, &flags, |_, (_, result)| ResultAndStates {
result,
states: Default::default(),
})
}

Expand All @@ -278,18 +258,19 @@ impl ExecutorExt for StarknetVMProcessor<'_> {
flags: SimulationFlag,
) -> Vec<Result<TxFeeInfo, ExecutionError>> {
self.simulate_with(transactions, &flags, |_, (_, res)| match res {
Ok((info, fee)) => {
ExecutionResult::Success { receipt, .. } => {
// if the transaction was reverted, return as error
if let Some(reason) = info.revert_error {
info!(target: LOG_TARGET, reason = %reason, "Estimating fee.");
Err(ExecutionError::TransactionReverted { revert_error: reason })
if let Some(reason) = receipt.revert_reason() {
info!(target: LOG_TARGET, %reason, "Estimating fee.");
Err(ExecutionError::TransactionReverted { revert_error: reason.to_string() })
} else {
Ok(fee)
Ok(receipt.fee().clone())
}
}
Err(e) => {
info!(target: LOG_TARGET, error = %e, "Estimating fee.");
Err(e)

ExecutionResult::Failed { error } => {
info!(target: LOG_TARGET, %error, "Estimating fee.");
Err(error)
}
})
}
Expand Down
89 changes: 55 additions & 34 deletions crates/katana/executor/src/implementation/blockifier/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,50 +59,71 @@ use starknet_api::transaction::{
use super::state::{CachedState, StateDb};
use super::CACHE_SIZE;
use crate::abstraction::{EntryPointCall, SimulationFlag};
use crate::ExecutionError;
use crate::utils::build_receipt;
use crate::{ExecutionError, ExecutionResult};

pub(super) fn transact<S: StateReader>(
tx: ExecutableTxWithHash,
state: &mut cached_state::CachedState<S>,
block_context: &BlockContext,
simulation_flags: &SimulationFlag,
) -> Result<(TransactionExecutionInfo, TxFeeInfo), ExecutionError> {
let validate = !simulation_flags.skip_validate;
let charge_fee = !simulation_flags.skip_fee_transfer;
tx: ExecutableTxWithHash,
) -> ExecutionResult {
fn transact_inner<S: StateReader>(
state: &mut cached_state::CachedState<S>,
block_context: &BlockContext,
simulation_flags: &SimulationFlag,
tx: Transaction,
) -> Result<(TransactionExecutionInfo, TxFeeInfo), ExecutionError> {
let validate = !simulation_flags.skip_validate;
let charge_fee = !simulation_flags.skip_fee_transfer;

let fee_type = get_fee_type_from_tx(&tx);
let info = match tx {
Transaction::AccountTransaction(tx) => {
tx.execute(state, block_context, charge_fee, validate)
}
Transaction::L1HandlerTransaction(tx) => {
tx.execute(state, block_context, charge_fee, validate)
}
}?;

// There are a few case where the `actual_fee` field of the transaction info is not set where
// the fee is skipped and thus not charged for the transaction (e.g. when the
// `skip_fee_transfer` is explicitly set, or when the transaction `max_fee` is set to 0). In
// these cases, we still want to calculate the fee.
let overall_fee = if info.actual_fee == Fee(0) {
calculate_tx_fee(&info.actual_resources, block_context, &fee_type)?.0
} else {
info.actual_fee.0
};

let transaction = to_executor_tx(tx);
let fee_type = get_fee_type_from_tx(&transaction);
let consts = block_context.versioned_constants();
let gas_consumed = calculate_tx_gas_vector(&info.actual_resources, consts)?.l1_gas;

let info = match transaction {
Transaction::AccountTransaction(tx) => {
tx.execute(state, block_context, charge_fee, validate)
}
Transaction::L1HandlerTransaction(tx) => {
tx.execute(state, block_context, charge_fee, validate)
}
}?;

// There are a few case where the `actual_fee` field of the transaction info is not set where
// the fee is skipped and thus not charged for the transaction (e.g. when the
// `skip_fee_transfer` is explicitly set, or when the transaction `max_fee` is set to 0). In
// these cases, we still want to calculate the fee.
let overall_fee = if info.actual_fee == Fee(0) {
calculate_tx_fee(&info.actual_resources, block_context, &fee_type)?.0
} else {
info.actual_fee.0
};
let (unit, gas_price) = match fee_type {
FeeType::Eth => {
(PriceUnit::Wei, block_context.block_info().gas_prices.eth_l1_gas_price)
}
FeeType::Strk => {
(PriceUnit::Fri, block_context.block_info().gas_prices.strk_l1_gas_price)
}
};

let gas_consumed =
calculate_tx_gas_vector(&info.actual_resources, block_context.versioned_constants())?
.l1_gas;
let fee = TxFeeInfo { gas_consumed, gas_price: gas_price.into(), unit, overall_fee };

let (unit, gas_price) = match fee_type {
FeeType::Eth => (PriceUnit::Wei, block_context.block_info().gas_prices.eth_l1_gas_price),
FeeType::Strk => (PriceUnit::Fri, block_context.block_info().gas_prices.strk_l1_gas_price),
};
Ok((info, fee))
}

match transact_inner(state, block_context, simulation_flags, to_executor_tx(tx.clone())) {
Ok((info, fee)) => {
// get the trace and receipt from the execution info
let trace = to_exec_info(info);
let receipt = build_receipt(tx.tx_ref(), fee, &trace);
ExecutionResult::new_success(receipt, trace)
}

let fee = TxFeeInfo { gas_consumed, gas_price: gas_price.into(), unit, overall_fee };
Ok((info, fee))
Err(e) => ExecutionResult::new_failed(e),
}
}

/// Perform a function call on a contract and retrieve the return values.
Expand Down
12 changes: 6 additions & 6 deletions crates/katana/executor/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use katana_primitives::receipt::{
MessageToL1, Receipt, TxExecutionResources,
};
use katana_primitives::trace::{CallInfo, TxExecInfo};
use katana_primitives::transaction::Tx;
use katana_primitives::transaction::TxRef;
use tracing::trace;

pub(crate) const LOG_TARGET: &str = "executor";
Expand Down Expand Up @@ -48,30 +48,30 @@ pub fn log_events(events: &[Event]) {
}
}

pub fn build_receipt(tx: &Tx, fee: TxFeeInfo, info: &TxExecInfo) -> Receipt {
pub(crate) fn build_receipt(tx: TxRef<'_>, fee: TxFeeInfo, info: &TxExecInfo) -> Receipt {
let events = events_from_exec_info(info);
let revert_error = info.revert_error.clone();
let messages_sent = l2_to_l1_messages_from_exec_info(info);
let actual_resources = parse_actual_resources(&info.actual_resources);

match tx {
Tx::Invoke(_) => Receipt::Invoke(InvokeTxReceipt {
TxRef::Invoke(_) => Receipt::Invoke(InvokeTxReceipt {
events,
fee,
revert_error,
messages_sent,
execution_resources: actual_resources,
}),

Tx::Declare(_) => Receipt::Declare(DeclareTxReceipt {
TxRef::Declare(_) => Receipt::Declare(DeclareTxReceipt {
events,
fee,
revert_error,
messages_sent,
execution_resources: actual_resources,
}),

Tx::L1Handler(tx) => Receipt::L1Handler(L1HandlerTxReceipt {
TxRef::L1Handler(tx) => Receipt::L1Handler(L1HandlerTxReceipt {
events,
fee,
revert_error,
Expand All @@ -80,7 +80,7 @@ pub fn build_receipt(tx: &Tx, fee: TxFeeInfo, info: &TxExecInfo) -> Receipt {
execution_resources: actual_resources,
}),

Tx::DeployAccount(tx) => Receipt::DeployAccount(DeployAccountTxReceipt {
TxRef::DeployAccount(tx) => Receipt::DeployAccount(DeployAccountTxReceipt {
events,
fee,
revert_error,
Expand Down

0 comments on commit 20f2bee

Please sign in to comment.