Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
refactor(execution): add messages info to ExecutionSummary (#1666)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yael-Starkware committed Mar 14, 2024
1 parent 936bbe7 commit b5c4339
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 121 deletions.
28 changes: 10 additions & 18 deletions crates/blockifier/src/blockifier/transaction_executor.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::vec::IntoIter;

use cairo_vm::vm::runners::builtin_runner::HASH_BUILTIN_NAME;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
use starknet_api::core::ClassHash;
use thiserror::Error;

use crate::blockifier::bouncer::BouncerInfo;
use crate::bouncer::calculate_message_l1_resources;
use crate::context::BlockContext;
use crate::execution::call_info::{CallInfo, MessageL1CostInfo};
use crate::execution::call_info::CallInfo;
use crate::fee::actual_cost::ActualCost;
use crate::fee::gas_usage::{get_messages_gas_usage, get_onchain_data_segment_length};
use crate::fee::gas_usage::get_onchain_data_segment_length;
use crate::state::cached_state::{
CachedState, CommitmentStateDiff, StagedTransactionalState, StateChangesKeys, StorageEntry,
TransactionalState,
Expand Down Expand Up @@ -104,18 +104,10 @@ impl<S: StateReader> TransactionExecutor<S> {
let tx_execution_summary = tx_execution_info.summarize();

// Count message to L1 resources.
let call_infos: IntoIter<&CallInfo> =
[&tx_execution_info.validate_call_info, &tx_execution_info.execute_call_info]
.iter()
.filter_map(|&call_info| call_info.as_ref())
.collect::<Vec<&CallInfo>>()
.into_iter();

let message_cost_info =
MessageL1CostInfo::calculate(call_infos, l1_handler_payload_size)?;

let starknet_gas_usage =
get_messages_gas_usage(&message_cost_info, l1_handler_payload_size);
let (message_segment_length, gas_usage) = calculate_message_l1_resources(
&tx_execution_summary.l2_to_l1_payload_lengths,
l1_handler_payload_size,
);

// Count additional OS resources.
let mut additional_os_resources = get_casm_hash_calculation_resources(
Expand All @@ -142,9 +134,9 @@ impl<S: StateReader> TransactionExecutor<S> {
// Finalize counting logic.
let bouncer_info = BouncerInfo::calculate(
&tx_execution_info.bouncer_resources,
starknet_gas_usage,
gas_usage,
additional_os_resources,
message_cost_info.message_segment_length,
message_segment_length,
state_diff_size,
tx_execution_summary.n_events,
)?;
Expand Down Expand Up @@ -189,7 +181,7 @@ impl<S: StateReader> TransactionExecutor<S> {
)?;

let (actual_cost, _bouncer_resources) = account_tx
.to_actual_cost_builder(tx_context)?
.to_actual_cost_builder(tx_context)
.with_validate_call_info(&validate_call_info)
.try_add_state_changes(&mut self.state)?
.build(&execution_resources)?;
Expand Down
31 changes: 26 additions & 5 deletions crates/blockifier/src/bouncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use serde::Deserialize;
use starknet_api::core::ClassHash;

use crate::blockifier::transaction_executor::TransactionExecutorResult;
use crate::execution::call_info::{ExecutionSummary, MessageL1CostInfo};
use crate::fee::gas_usage::{get_message_segment_length, get_messages_gas_usage};
use crate::state::cached_state::{StateChangesKeys, StorageEntry, TransactionalState};
use crate::state::state_api::StateReader;
use crate::transaction::objects::TransactionExecutionInfo;
use crate::transaction::objects::GasVector;

#[cfg(test)]
#[path = "bouncer_test.rs"]
Expand Down Expand Up @@ -112,14 +114,15 @@ impl TransactionalBouncer {

pub fn update_auxiliary_info<S: StateReader>(
&mut self,
tx_execution_info: &TransactionExecutionInfo,
tx_execution_summary: &ExecutionSummary,
state: &mut TransactionalState<'_, S>,
) -> TransactionExecutorResult<()> {
let tx_execution_summary = tx_execution_info.summarize();
self.transactional.executed_class_hashes.extend(tx_execution_summary.executed_class_hashes);
self.transactional
.executed_class_hashes
.extend(&tx_execution_summary.executed_class_hashes);
self.transactional
.visited_storage_entries
.extend(tx_execution_summary.visited_storage_entries);
.extend(&tx_execution_summary.visited_storage_entries);
let tx_state_changes_keys = state.get_actual_state_changes()?.into_keys();
self.transactional.state_changes_keys =
tx_state_changes_keys.difference(&self.bouncer.state_changes_keys);
Expand All @@ -135,3 +138,21 @@ impl TransactionalBouncer {
self.bouncer
}
}

/// Calculates the L1 resources used by L1<>L2 messages.
/// Returns the total message segment length and the L1 gas usage.
pub fn calculate_message_l1_resources(
l2_to_l1_payload_lengths: &[usize],
l1_handler_payload_size: Option<usize>,
) -> (usize, GasVector) {
let message_segment_length =
get_message_segment_length(l2_to_l1_payload_lengths, l1_handler_payload_size);
let gas_usage = get_messages_gas_usage(
&MessageL1CostInfo {
l2_to_l1_payload_lengths: l2_to_l1_payload_lengths.to_owned(),
message_segment_length,
},
l1_handler_payload_size,
);
(message_segment_length, gas_usage)
}
76 changes: 36 additions & 40 deletions crates/blockifier/src/execution/call_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ use starknet_api::transaction::{EventContent, L2ToL1Payload};
use crate::execution::entry_point::CallEntryPoint;
use crate::fee::gas_usage::get_message_segment_length;
use crate::state::cached_state::StorageEntry;
use crate::transaction::errors::TransactionExecutionError;
use crate::transaction::objects::TransactionExecutionResult;

#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
pub struct Retdata(pub Vec<StarkFelt>);
Expand Down Expand Up @@ -43,16 +41,16 @@ impl MessageL1CostInfo {
pub fn calculate<'a>(
call_infos: impl Iterator<Item = &'a CallInfo>,
l1_handler_payload_size: Option<usize>,
) -> TransactionExecutionResult<Self> {
) -> Self {
let mut l2_to_l1_payload_lengths = Vec::new();
for call_info in call_infos {
l2_to_l1_payload_lengths.extend(call_info.get_sorted_l2_to_l1_payload_lengths()?);
l2_to_l1_payload_lengths.extend(call_info.get_l2_to_l1_payload_lengths());
}

let message_segment_length =
get_message_segment_length(&l2_to_l1_payload_lengths, l1_handler_payload_size);

Ok(Self { l2_to_l1_payload_lengths, message_segment_length })
Self { l2_to_l1_payload_lengths, message_segment_length }
}
}

Expand All @@ -70,6 +68,10 @@ pub struct OrderedL2ToL1Message {
pub message: MessageToL1,
}

pub fn get_payload_lengths(l2_to_l1_messages: &[OrderedL2ToL1Message]) -> Vec<usize> {
l2_to_l1_messages.iter().map(|message| message.message.payload.0.len()).collect()
}

/// Represents the effects of executing a single entry point.
#[cfg_attr(test, derive(Clone))]
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
Expand All @@ -94,6 +96,7 @@ struct ExecutionResourcesDef {
pub struct ExecutionSummary {
pub executed_class_hashes: HashSet<ClassHash>,
pub visited_storage_entries: HashSet<StorageEntry>,
pub l2_to_l1_payload_lengths: Vec<usize>,
pub n_events: usize,
}

Expand All @@ -103,6 +106,7 @@ impl Add for ExecutionSummary {
fn add(mut self, other: Self) -> Self {
self.executed_class_hashes.extend(other.executed_class_hashes);
self.visited_storage_entries.extend(other.visited_storage_entries);
self.l2_to_l1_payload_lengths.extend(other.l2_to_l1_payload_lengths);
self.n_events += other.n_events;
self
}
Expand All @@ -117,6 +121,7 @@ impl Sum for ExecutionSummary {
#[derive(Debug, Default)]
pub struct TestExecutionSummary {
pub num_of_events: usize,
pub num_of_messages: usize,
pub class_hash: ClassHash,
pub storage_address: ContractAddress,
pub storage_key: StorageKey,
Expand All @@ -125,12 +130,14 @@ pub struct TestExecutionSummary {
impl TestExecutionSummary {
pub fn new(
num_of_events: usize,
num_of_messages: usize,
class_hash: ClassHash,
storage_address: &str,
storage_key: &str,
) -> Self {
TestExecutionSummary {
num_of_events,
num_of_messages,
class_hash,
storage_address: ContractAddress(patricia_key!(storage_address)),
storage_key: StorageKey(patricia_key!(storage_key)),
Expand All @@ -146,6 +153,15 @@ impl TestExecutionSummary {
},
execution: CallExecution {
events: (0..self.num_of_events).map(|_| OrderedEvent::default()).collect(),
l2_to_l1_messages: (0..self.num_of_messages)
.map(|i| OrderedL2ToL1Message {
order: i,
message: MessageToL1 {
to_address: EthAddress::default(),
payload: L2ToL1Payload(vec![StarkFelt::default()]),
},
})
.collect(),
..Default::default()
},
accessed_storage_keys: vec![self.storage_key].into_iter().collect(),
Expand Down Expand Up @@ -174,46 +190,18 @@ impl CallInfo {
CallInfoIter { call_infos }
}

/// Returns a list of Starknet L2ToL1Payload length collected during the execution, sorted
/// by the order in which they were sent.
pub fn get_sorted_l2_to_l1_payload_lengths(&self) -> TransactionExecutionResult<Vec<usize>> {
let n_messages = self.iter().map(|call| call.execution.l2_to_l1_messages.len()).sum();
let mut starknet_l2_to_l1_payload_lengths: Vec<Option<usize>> = vec![None; n_messages];

for call_info in self.iter() {
for ordered_message_content in &call_info.execution.l2_to_l1_messages {
let message_order = ordered_message_content.order;
if message_order >= n_messages {
return Err(TransactionExecutionError::InvalidOrder {
object: "L2-to-L1 message".to_string(),
order: message_order,
max_order: n_messages,
});
}
starknet_l2_to_l1_payload_lengths[message_order] =
Some(ordered_message_content.message.payload.0.len());
}
}

starknet_l2_to_l1_payload_lengths.into_iter().enumerate().try_fold(
Vec::new(),
|mut acc, (i, option)| match option {
Some(value) => {
acc.push(value);
Ok(acc)
}
None => Err(TransactionExecutionError::UnexpectedHoles {
object: "L2-to-L1 message".to_string(),
order: i,
}),
},
)
pub fn get_l2_to_l1_payload_lengths(&self) -> Vec<usize> {
self.iter().fold(Vec::new(), |mut acc, call_info| {
acc.extend(get_payload_lengths(&call_info.execution.l2_to_l1_messages));
acc
})
}

pub fn summarize(&self) -> ExecutionSummary {
let mut executed_class_hashes: HashSet<ClassHash> = HashSet::new();
let mut visited_storage_entries: HashSet<StorageEntry> = HashSet::new();
let mut n_events: usize = 0;
let mut l2_to_l1_payload_lengths = Vec::new();

for call_info in self.iter() {
let class_hash =
Expand All @@ -227,9 +215,17 @@ impl CallInfo {
visited_storage_entries.extend(call_storage_entries);

n_events += call_info.execution.events.len();

l2_to_l1_payload_lengths
.extend(get_payload_lengths(&call_info.execution.l2_to_l1_messages));
}

ExecutionSummary { executed_class_hashes, visited_storage_entries, n_events }
ExecutionSummary {
executed_class_hashes,
visited_storage_entries,
l2_to_l1_payload_lengths,
n_events,
}
}
}

Expand Down
18 changes: 9 additions & 9 deletions crates/blockifier/src/fee/actual_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ impl ActualCost {
pub fn builder_for_l1_handler<'a>(
tx_context: Arc<TransactionContext>,
l1_handler_payload_size: usize,
) -> TransactionExecutionResult<ActualCostBuilder<'a>> {
) -> ActualCostBuilder<'a> {
let signature_length = 0; // Signature is validated on L1.
Ok(ActualCostBuilder::new(
ActualCostBuilder::new(
tx_context,
TransactionType::L1Handler,
l1_handler_payload_size,
signature_length,
)?
)
.without_sender_address()
.with_l1_payload_size(l1_handler_payload_size))
.with_l1_payload_size(l1_handler_payload_size)
}
}

Expand All @@ -67,24 +67,24 @@ impl<'a> ActualCostBuilder<'a> {
tx_type: TransactionType,
calldata_length: usize,
signature_length: usize,
) -> TransactionExecutionResult<Self> {
Ok(Self {
) -> Self {
Self {
starknet_resources: StarknetResources::new(
calldata_length,
signature_length,
None,
StateChangesCount::default(),
None,
iter::empty(),
)?,
),
sender_address: Some(tx_context.tx_info.sender_address()),
tx_context,
tx_type,
validate_call_info: None,
execute_call_info: None,
state_changes: StateChanges::default(),
n_reverted_steps: 0,
})
}
}

pub fn without_sender_address(mut self) -> Self {
Expand Down Expand Up @@ -164,7 +164,7 @@ impl<'a> ActualCostBuilder<'a> {
self.validate_call_info.into_iter().chain(self.execute_call_info);

// Set the events and messages resources from the transaction's call infos.
self.starknet_resources.set_events_and_messages_resources(non_optional_call_infos)?;
self.starknet_resources.set_events_and_messages_resources(non_optional_call_infos);

let mut actual_resources = calculate_tx_resources(
&self.tx_context.block_context.versioned_constants,
Expand Down
Loading

0 comments on commit b5c4339

Please sign in to comment.