Skip to content

Commit

Permalink
refacto: clean trace api (#1483)
Browse files Browse the repository at this point in the history
  • Loading branch information
anondev1993 committed Mar 5, 2024
1 parent c06c385 commit 5e68494
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 91 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- chore(rpc): clean trace api
- feat(rpc): added state diff real value in trace api
- chore: update cairo-vm commit and update gas per op
- refactor(rpc): use single arc instance of starknet rpc
Expand Down
110 changes: 19 additions & 91 deletions crates/client/rpc/src/trace_api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::collections::HashMap;

use blockifier::execution::contract_class::{ContractClass, ContractClassV1};
use blockifier::execution::entry_point::CallInfo;
use blockifier::state::cached_state::CommitmentStateDiff;
Expand All @@ -10,7 +8,6 @@ use log::error;
use mc_genesis_data_provider::GenesisProvider;
use mc_rpc_core::utils::{blockifier_to_rpc_state_diff_types, get_block_by_block_hash};
use mc_rpc_core::{StarknetReadRpcApiServer, StarknetTraceRpcApiServer};
use mc_storage::StorageOverride;
use mp_felt::Felt252Wrapper;
use mp_hashers::HasherT;
use mp_simulations::{SimulationFlags, TransactionSimulationResult};
Expand All @@ -23,7 +20,7 @@ use sc_transaction_pool_api::TransactionPool;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use starknet_api::api_core::{ClassHash, ContractAddress};
use starknet_api::api_core::ClassHash;
use starknet_core::types::{
BlockId, BroadcastedTransaction, DeclareTransactionTrace, DeployAccountTransactionTrace, ExecuteInvocation,
FeeEstimate, InvokeTransactionTrace, L1HandlerTransactionTrace, RevertedInvocation, SimulatedTransaction,
Expand Down Expand Up @@ -90,10 +87,8 @@ where
StarknetRpcApiError::ContractError
})?;

let storage_override = self.overrides.for_block_hash(self.client.as_ref(), substrate_block_hash);
let simulated_transactions =
tx_execution_infos_to_simulated_transactions(&**storage_override, substrate_block_hash, tx_types, res)
.map_err(StarknetRpcApiError::from)?;
tx_execution_infos_to_simulated_transactions(tx_types, res).map_err(StarknetRpcApiError::from)?;

Ok(simulated_transactions)
}
Expand Down Expand Up @@ -231,8 +226,6 @@ where
let state_diff = blockifier_to_rpc_state_diff_types(commitment_state_diff)
.map_err(|_| ConvertCallInfoToExecuteInvocationError::ConvertStateDiffFailed)?;
tx_execution_infos_to_tx_trace(
&**storage_override,
substrate_block_hash,
// Safe to unwrap coz re_execute returns exactly one ExecutionInfo for each tx
TxType::from(block_transactions.get(tx_idx).unwrap()),
&tx_exec_info,
Expand Down Expand Up @@ -277,9 +270,8 @@ fn collect_call_info_ordered_messages(call_info: &CallInfo) -> Vec<starknet_core
.execution
.l2_to_l1_messages
.iter()
.enumerate()
.map(|(index, message)| starknet_core::types::OrderedMessage {
order: index as u64,
.map(|message| starknet_core::types::OrderedMessage {
order: message.order as u64,
payload: message.message.payload.0.iter().map(|x| (*x).into()).collect(),
to_address: FieldElement::from_byte_slice_be(message.message.to_address.0.to_fixed_bytes().as_slice())
.unwrap(),
Expand Down Expand Up @@ -315,22 +307,14 @@ pub enum TryFuntionInvocationFromCallInfoError {
ContractNotFound,
}

fn try_get_funtion_invocation_from_call_info<B: BlockT>(
storage_override: &dyn StorageOverride<B>,
substrate_block_hash: B::Hash,
fn try_get_function_invocation_from_call_info(
call_info: &CallInfo,
class_hash_cache: &mut HashMap<ContractAddress, FieldElement>,
) -> Result<starknet_core::types::FunctionInvocation, TryFuntionInvocationFromCallInfoError> {
let messages = collect_call_info_ordered_messages(call_info);
let events = blockifier_to_starknet_rs_ordered_events(&call_info.execution.events);

let inner_calls = call_info
.inner_calls
.iter()
.map(|call| {
try_get_funtion_invocation_from_call_info(storage_override, substrate_block_hash, call, class_hash_cache)
})
.collect::<Result<_, _>>()?;
let inner_calls =
call_info.inner_calls.iter().map(try_get_function_invocation_from_call_info).collect::<Result<_, _>>()?;

call_info.get_sorted_l2_to_l1_payloads_length()?;

Expand All @@ -351,23 +335,8 @@ fn try_get_funtion_invocation_from_call_info<B: BlockT>(
blockifier::execution::entry_point::CallType::Delegate => starknet_core::types::CallType::Delegate,
};

// Blockifier call info does not give use the class_hash "if it can be deducted from the storage
// address". We have to do this decution ourselves here
let class_hash = if let Some(class_hash) = call_info.call.class_hash {
class_hash.0.into()
} else if let Some(cached_hash) = class_hash_cache.get(&call_info.call.storage_address) {
*cached_hash
} else {
// Compute and cache the class hash
let computed_hash = storage_override
.contract_class_hash_by_address(substrate_block_hash, call_info.call.storage_address)
.ok_or_else(|| TryFuntionInvocationFromCallInfoError::ContractNotFound)?;

let computed_hash = FieldElement::from_byte_slice_be(computed_hash.0.bytes()).unwrap();
class_hash_cache.insert(call_info.call.storage_address, computed_hash);

computed_hash
};
// The class hash in the call_info is computed during execution and will be set here.
let class_hash = call_info.call.class_hash.expect("Class hash should be computed after execution").0.into();

Ok(starknet_core::types::FunctionInvocation {
contract_address: call_info.call.storage_address.0.0.into(),
Expand All @@ -384,56 +353,29 @@ fn try_get_funtion_invocation_from_call_info<B: BlockT>(
})
}

fn tx_execution_infos_to_tx_trace<B: BlockT>(
storage_override: &dyn StorageOverride<B>,
substrate_block_hash: B::Hash,
fn tx_execution_infos_to_tx_trace(
tx_type: TxType,
tx_exec_info: &TransactionExecutionInfo,
state_diff: Option<StateDiff>,
) -> Result<TransactionTrace, ConvertCallInfoToExecuteInvocationError> {
let mut class_hash_cache: HashMap<ContractAddress, FieldElement> = HashMap::new();

// If simulated with `SimulationFlag::SkipValidate` this will be `None`
// therefore we cannot unwrap it
let validate_invocation = tx_exec_info
.validate_call_info
.as_ref()
.map(|call_info| {
try_get_funtion_invocation_from_call_info(
storage_override,
substrate_block_hash,
call_info,
&mut class_hash_cache,
)
})
.transpose()?;
let validate_invocation =
tx_exec_info.validate_call_info.as_ref().map(try_get_function_invocation_from_call_info).transpose()?;
// If simulated with `SimulationFlag::SkipFeeCharge` this will be `None`
// therefore we cannot unwrap it
let fee_transfer_invocation = tx_exec_info
.fee_transfer_call_info
.as_ref()
.map(|call_info| {
try_get_funtion_invocation_from_call_info(
storage_override,
substrate_block_hash,
call_info,
&mut class_hash_cache,
)
})
.transpose()?;
let fee_transfer_invocation =
tx_exec_info.fee_transfer_call_info.as_ref().map(try_get_function_invocation_from_call_info).transpose()?;

let tx_trace = match tx_type {
TxType::Invoke => TransactionTrace::Invoke(InvokeTransactionTrace {
validate_invocation,
execute_invocation: if let Some(e) = &tx_exec_info.revert_error {
ExecuteInvocation::Reverted(RevertedInvocation { revert_reason: e.clone() })
} else {
ExecuteInvocation::Success(try_get_funtion_invocation_from_call_info(
storage_override,
substrate_block_hash,
ExecuteInvocation::Success(try_get_function_invocation_from_call_info(
// Safe to unwrap because is only `None` for `Declare` txs
tx_exec_info.execute_call_info.as_ref().unwrap(),
&mut class_hash_cache,
)?)
},
fee_transfer_invocation,
Expand All @@ -447,24 +389,18 @@ fn tx_execution_infos_to_tx_trace<B: BlockT>(
TxType::DeployAccount => {
TransactionTrace::DeployAccount(DeployAccountTransactionTrace {
validate_invocation,
constructor_invocation: try_get_funtion_invocation_from_call_info(
storage_override,
substrate_block_hash,
constructor_invocation: try_get_function_invocation_from_call_info(
// Safe to unwrap because is only `None` for `Declare` txs
tx_exec_info.execute_call_info.as_ref().unwrap(),
&mut class_hash_cache,
)?,
fee_transfer_invocation,
state_diff,
})
}
TxType::L1Handler => TransactionTrace::L1Handler(L1HandlerTransactionTrace {
function_invocation: try_get_funtion_invocation_from_call_info(
storage_override,
substrate_block_hash,
function_invocation: try_get_function_invocation_from_call_info(
// Safe to unwrap because is only `None` for `Declare` txs
tx_exec_info.execute_call_info.as_ref().unwrap(),
&mut class_hash_cache,
)?,
state_diff: None,
}),
Expand All @@ -473,9 +409,7 @@ fn tx_execution_infos_to_tx_trace<B: BlockT>(
Ok(tx_trace)
}

fn tx_execution_infos_to_simulated_transactions<B: BlockT>(
storage_override: &dyn StorageOverride<B>,
substrate_block_hash: B::Hash,
fn tx_execution_infos_to_simulated_transactions(
tx_types: Vec<TxType>,
transaction_execution_results: Vec<(CommitmentStateDiff, TransactionSimulationResult)>,
) -> Result<Vec<SimulatedTransaction>, ConvertCallInfoToExecuteInvocationError> {
Expand All @@ -486,13 +420,7 @@ fn tx_execution_infos_to_simulated_transactions<B: BlockT>(
let state_diff = blockifier_to_rpc_state_diff_types(state_diff)
.map_err(|_| ConvertCallInfoToExecuteInvocationError::ConvertStateDiffFailed)?;

let transaction_trace = tx_execution_infos_to_tx_trace(
storage_override,
substrate_block_hash,
tx_type,
&tx_exec_info,
Some(state_diff),
)?;
let transaction_trace = tx_execution_infos_to_tx_trace(tx_type, &tx_exec_info, Some(state_diff))?;
let gas_consumed =
tx_exec_info.execute_call_info.as_ref().map(|x| x.execution.gas_consumed).unwrap_or_default();
let overall_fee = tx_exec_info.actual_fee.0 as u64;
Expand Down

0 comments on commit 5e68494

Please sign in to comment.