Skip to content

Commit

Permalink
Merge pull request #2566 from eqlabs/sistemd/binary-search-fee-estima…
Browse files Browse the repository at this point in the history
…tion

feat(execution): binary search fee estimation
  • Loading branch information
sistemd authored Feb 14, 2025
2 parents 55a18f7 + d22581b commit aa642d0
Show file tree
Hide file tree
Showing 8 changed files with 2,395 additions and 106 deletions.
110 changes: 69 additions & 41 deletions crates/executor/src/estimate.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use blockifier::transaction::objects::TransactionExecutionInfo;
use blockifier::transaction::transaction_execution::Transaction;
use blockifier::transaction::transactions::ExecutableTransaction;
use starknet_api::transaction::fields::GasVectorComputationMode;

use super::error::TransactionExecutionError;
use super::execution_state::ExecutionState;
use super::transaction::transaction_hash;
use super::types::FeeEstimate;
use crate::transaction::{
execute_transaction,
find_l2_gas_limit_and_execute_transaction,
l2_gas_accounting_enabled,
};

pub fn estimate(
execution_state: ExecutionState<'_>,
Expand All @@ -13,54 +20,75 @@ pub fn estimate(

let (mut state, block_context) = execution_state.starknet_state()?;

let mut fees = Vec::with_capacity(transactions.len());
for (transaction_idx, transaction) in transactions.into_iter().enumerate() {
let _span = tracing::debug_span!("estimate", transaction_hash=%super::transaction::transaction_hash(&transaction), %block_number, %transaction_idx).entered();
transactions
.into_iter()
.enumerate()
.map(|(tx_index, mut tx)| {
let _span = tracing::debug_span!(
"estimate",
block_number = %block_number,
transaction_hash = %transaction_hash(&tx),
transaction_index = %tx_index
)
.entered();

let fee_type = super::transaction::fee_type(&transaction);
let gas_vector_computation_mode =
super::transaction::gas_vector_computation_mode(&transaction);
let minimal_l1_gas_amount_vector = match &transaction {
let gas_vector_computation_mode = super::transaction::gas_vector_computation_mode(&tx);
let tx_info = if l2_gas_accounting_enabled(
&tx,
&state,
&block_context,
&gas_vector_computation_mode,
)? {
find_l2_gas_limit_and_execute_transaction(
&mut tx,
tx_index,
&mut state,
&block_context,
)?
} else {
execute_transaction(&tx, tx_index, &mut state, &block_context)?
};

tracing::trace!(
actual_fee = %tx_info.receipt.fee.0,
actual_resources = ?tx_info.receipt.resources,
"Transaction estimation finished"
);

Ok(FeeEstimate::from_tx_and_tx_info(
&tx,
&tx_info,
&gas_vector_computation_mode,
&block_context,
))
})
.collect()
}

impl FeeEstimate {
pub(crate) fn from_tx_and_tx_info(
transaction: &Transaction,
tx_info: &TransactionExecutionInfo,
gas_vector_computation_mode: &GasVectorComputationMode,
block_context: &blockifier::context::BlockContext,
) -> Self {
let fee_type = super::transaction::fee_type(transaction);
let minimal_gas_vector = match transaction {
Transaction::Account(account_transaction) => {
Some(blockifier::fee::gas_usage::estimate_minimal_gas_vector(
&block_context,
block_context,
account_transaction,
&gas_vector_computation_mode,
gas_vector_computation_mode,
))
}
Transaction::L1Handler(_) => None,
};
let tx_info: Result<
blockifier::transaction::objects::TransactionExecutionInfo,
blockifier::transaction::errors::TransactionExecutionError,
> = transaction.execute(&mut state, &block_context);

match tx_info {
Ok(tx_info) => {
if let Some(revert_error) = tx_info.revert_error {
let revert_string = revert_error.to_string();
tracing::debug!(revert_error=%revert_string, "Transaction reverted");
return Err(TransactionExecutionError::ExecutionError {
transaction_index: transaction_idx,
error: revert_string,
error_stack: revert_error.into(),
});
}

tracing::trace!(actual_fee=%tx_info.receipt.fee.0, actual_resources=?tx_info.receipt.resources, "Transaction estimation finished");

fees.push(FeeEstimate::from_tx_info_and_gas_price(
&tx_info,
block_context.block_info(),
fee_type,
&minimal_l1_gas_amount_vector,
));
}
Err(error) => {
tracing::debug!(%error, %transaction_idx, "Transaction estimation failed");
return Err(TransactionExecutionError::new(transaction_idx, error));
}
}
FeeEstimate::from_tx_info_and_gas_price(
tx_info,
block_context.block_info(),
fee_type,
&minimal_gas_vector,
)
}
Ok(fees)
}
111 changes: 54 additions & 57 deletions crates/executor/src/simulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ use super::error::TransactionExecutionError;
use super::execution_state::ExecutionState;
use super::types::{FeeEstimate, TransactionSimulation, TransactionTrace};
use crate::error_stack::ErrorStack;
use crate::transaction::transaction_hash;
use crate::transaction::{
execute_transaction,
find_l2_gas_limit_and_execute_transaction,
l2_gas_accounting_enabled,
transaction_hash,
};
use crate::types::{
DataAvailabilityResources,
DeclareTransactionTrace,
Expand Down Expand Up @@ -86,66 +91,58 @@ pub fn simulate(

let (mut state, block_context) = execution_state.starknet_state()?;

let mut simulations = Vec::with_capacity(transactions.len());
for (transaction_idx, transaction) in transactions.into_iter().enumerate() {
let _span = tracing::debug_span!("simulate", transaction_hash=%super::transaction::transaction_hash(&transaction), %block_number, %transaction_idx).entered();
transactions
.into_iter()
.enumerate()
.map(|(tx_index, mut tx)| {
let _span = tracing::debug_span!(
"simulate",
block_number = %block_number,
transaction_hash = %transaction_hash(&tx),
transaction_index = %tx_index
)
.entered();

let gas_vector_computation_mode = super::transaction::gas_vector_computation_mode(&tx);
let mut tx_state = CachedState::<_>::create_transactional(&mut state);
let tx_info = if l2_gas_accounting_enabled(
&tx,
&tx_state,
&block_context,
&gas_vector_computation_mode,
)? {
find_l2_gas_limit_and_execute_transaction(
&mut tx,
tx_index,
&mut tx_state,
&block_context,
)?
} else {
execute_transaction(&tx, tx_index, &mut tx_state, &block_context)?
};
let state_diff = to_state_diff(&mut tx_state, transaction_declared_deprecated_class(&tx))?;
tx_state.commit();

let transaction_type = transaction_type(&transaction);
let transaction_declared_deprecated_class_hash =
transaction_declared_deprecated_class(&transaction);
let fee_type = super::transaction::fee_type(&transaction);
let gas_vector_computation_mode =
super::transaction::gas_vector_computation_mode(&transaction);
tracing::trace!(actual_fee=%tx_info.receipt.fee.0, actual_resources=?tx_info.receipt.resources, "Transaction simulation finished");

let minimal_l1_gas_amount_vector = match &transaction {
Transaction::Account(account_transaction) => {
Some(blockifier::fee::gas_usage::estimate_minimal_gas_vector(
Ok(TransactionSimulation {
fee_estimation: FeeEstimate::from_tx_and_tx_info(
&tx,
&tx_info,
&gas_vector_computation_mode,
&block_context,
account_transaction,
),
trace: to_trace(
transaction_type(&tx),
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
))
}
Transaction::L1Handler(_) => None,
};

let mut tx_state = CachedState::<_>::create_transactional(&mut state);
let tx_info = transaction.execute(&mut tx_state, &block_context);
let state_diff = to_state_diff(&mut tx_state, transaction_declared_deprecated_class_hash)?;
tx_state.commit();

match tx_info {
Ok(tx_info) => {
if let Some(revert_error) = &tx_info.revert_error {
let revert_string = revert_error.to_string();
tracing::trace!(revert_error=%revert_string, "Transaction reverted");
}

tracing::trace!(actual_fee=%tx_info.receipt.fee.0, actual_resources=?tx_info.receipt.resources, "Transaction simulation finished");

simulations.push(TransactionSimulation {
fee_estimation: FeeEstimate::from_tx_info_and_gas_price(
&tx_info,
block_context.block_info(),
fee_type,
&minimal_l1_gas_amount_vector,
),
trace: to_trace(
transaction_type,
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
block_context.block_info().use_kzg_da,
),
});
}
Err(error) => {
tracing::debug!(%error, %transaction_idx, "Transaction simulation failed");
return Err(TransactionExecutionError::new(transaction_idx, error));
}
}
}
Ok(simulations)
block_context.block_info().use_kzg_da,
),
})
})
.collect()
}

pub fn trace(
Expand Down
Loading

0 comments on commit aa642d0

Please sign in to comment.