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

refactor(execution, native_blockifier): make TransactionExecutor.execute() work w/o Py objects #1414

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion crates/native_blockifier/src/py_block_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ use blockifier::state::cached_state::{
CachedState, GlobalContractCache, GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST,
};
use blockifier::state::state_api::State;
use blockifier::transaction::objects::TransactionExecutionInfo;
use blockifier::transaction::transaction_execution::Transaction;
use blockifier::versioned_constants::VersionedConstants;
use pyo3::prelude::*;
use serde::Serialize;
use starknet_api::block::{BlockNumber, BlockTimestamp};
use starknet_api::core::{ChainId, ContractAddress};
use starknet_api::hash::StarkFelt;
Expand All @@ -20,6 +23,7 @@ use crate::errors::{
NativeBlockifierResult,
};
use crate::py_state_diff::{PyBlockInfo, PyStateDiff};
use crate::py_transaction::py_tx;
use crate::py_transaction_execution_info::PyBouncerInfo;
use crate::py_utils::{int_to_chain_id, py_attr, versioned_constants_with_overrides, PyFelt};
use crate::state_readers::papyrus_state::PapyrusReader;
Expand All @@ -30,6 +34,14 @@ use crate::transaction_executor::{RawTransactionExecutionInfo, TransactionExecut
#[path = "py_block_executor_test.rs"]
mod py_block_executor_test;

#[pyclass]
#[derive(Debug, Serialize)]
pub(crate) struct TypedTransactionExecutionInfo {
#[serde(flatten)]
pub info: TransactionExecutionInfo,
pub tx_type: String,
}

#[pyclass]
pub struct PyBlockExecutor {
pub general_config: PyGeneralConfig,
Expand Down Expand Up @@ -104,7 +116,14 @@ impl PyBlockExecutor {
raw_contract_class: Option<&str>,
) -> NativeBlockifierResult<(RawTransactionExecutionInfo, PyBouncerInfo)> {
let charge_fee = true;
self.tx_executor().execute(tx, raw_contract_class, charge_fee)
let tx_type: &str = tx.getattr("tx_type")?.getattr("name")?.extract()?;
let tx: Transaction = py_tx(tx, raw_contract_class)?;
let (tx_execution_info, py_bouncer_info) = self.tx_executor().execute(tx, charge_fee)?;
let typed_tx_execution_info =
TypedTransactionExecutionInfo { info: tx_execution_info, tx_type: tx_type.to_string() };
let raw_tx_execution_info = serde_json::to_vec(&typed_tx_execution_info)?;

Ok((raw_tx_execution_info, py_bouncer_info))
}

/// Returns the state diff and a list of contract class hash with the corresponding list of
Expand Down
21 changes: 12 additions & 9 deletions crates/native_blockifier/src/py_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use blockifier::state::cached_state::{
};
use blockifier::state::state_api::StateReader;
use blockifier::transaction::account_transaction::AccountTransaction;
use blockifier::transaction::objects::{TransactionExecutionResult, TransactionInfo};
use blockifier::transaction::objects::{
TransactionExecutionInfo, TransactionExecutionResult, TransactionInfo,
};
use blockifier::transaction::transaction_execution::Transaction;
use blockifier::versioned_constants::VersionedConstants;
use pyo3::prelude::*;
use starknet_api::core::Nonce;
Expand All @@ -16,11 +19,11 @@ use starknet_api::hash::StarkFelt;
use crate::errors::NativeBlockifierResult;
use crate::py_block_executor::{into_block_context_args, PyGeneralConfig};
use crate::py_state_diff::PyBlockInfo;
use crate::py_transaction::py_account_tx;
use crate::py_transaction::{py_account_tx, py_tx};
use crate::py_transaction_execution_info::PyBouncerInfo;
use crate::py_utils::{versioned_constants_with_overrides, PyFelt};
use crate::state_readers::py_state_reader::PyStateReader;
use crate::transaction_executor::{RawTransactionExecutionInfo, TransactionExecutor};
use crate::transaction_executor::TransactionExecutor;

/// Manages transaction validation for pre-execution flows.
#[pyclass]
Expand Down Expand Up @@ -77,8 +80,7 @@ impl PyValidator {
// before `__validate_deploy__`. The execution already includes all necessary validations,
// so they are skipped here.
if let AccountTransaction::DeployAccount(_deploy_account_tx) = account_tx {
let (_raw_tx_execution_info, _py_bouncer_info) =
self.execute(tx, raw_contract_class)?;
let (_tx_execution_info, _py_bouncer_info) = self.execute(tx, raw_contract_class)?;
// TODO(Ayelet, 09/11/2023): Check call succeeded.

return Ok(());
Expand Down Expand Up @@ -132,20 +134,21 @@ impl PyValidator {

Ok(Self { max_nonce_for_validation_skip: Nonce(StarkFelt::ONE), tx_executor })
}
}

impl PyValidator {
/// Applicable solely to account deployment transactions: the execution of the constructor
/// is required before they can be validated.
fn execute(
&mut self,
tx: &PyAny,
raw_contract_class: Option<&str>,
) -> NativeBlockifierResult<(RawTransactionExecutionInfo, PyBouncerInfo)> {
) -> NativeBlockifierResult<(TransactionExecutionInfo, PyBouncerInfo)> {
let limit_execution_steps_by_resource_bounds = true;
self.tx_executor.execute(tx, raw_contract_class, limit_execution_steps_by_resource_bounds)
let tx: Transaction = py_tx(tx, raw_contract_class)?;
self.tx_executor.execute(tx, limit_execution_steps_by_resource_bounds)
}
}

impl PyValidator {
fn perform_pre_validation_stage(
&mut self,
account_tx: &AccountTransaction,
Expand Down
28 changes: 5 additions & 23 deletions crates/native_blockifier/src/transaction_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,15 @@ use blockifier::transaction::transaction_execution::Transaction;
use blockifier::transaction::transactions::{ExecutableTransaction, ValidatableTransaction};
use cairo_vm::vm::runners::builtin_runner::HASH_BUILTIN_NAME;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources as VmExecutionResources;
use pyo3::prelude::*;
use serde::Serialize;
use starknet_api::core::ClassHash;

use crate::errors::{NativeBlockifierError, NativeBlockifierResult};
use crate::py_state_diff::PyStateDiff;
use crate::py_transaction::py_tx;
use crate::py_transaction_execution_info::PyBouncerInfo;
use crate::py_utils::PyFelt;

pub(crate) type RawTransactionExecutionInfo = Vec<u8>;

#[pyclass]
#[derive(Debug, Serialize)]
pub(crate) struct TypedTransactionExecutionInfo {
#[serde(flatten)]
info: TransactionExecutionInfo,
tx_type: String,
}

// TODO(Gilad): make this hold TransactionContext instead of BlockContext.
pub struct TransactionExecutor<S: StateReader> {
pub block_context: BlockContext,
Expand Down Expand Up @@ -73,12 +62,9 @@ impl<S: StateReader> TransactionExecutor<S> {
/// (used for counting purposes).
pub fn execute(
&mut self,
tx: &PyAny,
raw_contract_class: Option<&str>,
tx: Transaction,
charge_fee: bool,
) -> NativeBlockifierResult<(RawTransactionExecutionInfo, PyBouncerInfo)> {
let tx_type: &str = tx.getattr("tx_type")?.getattr("name")?.extract()?;
let tx: Transaction = py_tx(tx, raw_contract_class)?;
) -> NativeBlockifierResult<(TransactionExecutionInfo, PyBouncerInfo)> {
let l1_handler_payload_size: usize =
if let Transaction::L1HandlerTransaction(l1_handler_tx) = &tx {
l1_handler_tx.payload_size()
Expand Down Expand Up @@ -125,11 +111,7 @@ impl<S: StateReader> TransactionExecutor<S> {
let state_diff_size = 0;

// Finalize counting logic.
let typed_tx_execution_info = TypedTransactionExecutionInfo {
info: tx_execution_info,
tx_type: tx_type.to_string(),
};
let actual_resources = &typed_tx_execution_info.info.actual_resources;
let actual_resources = &tx_execution_info.actual_resources;
let py_bouncer_info = PyBouncerInfo::calculate(
actual_resources,
additional_os_resources,
Expand All @@ -140,8 +122,8 @@ impl<S: StateReader> TransactionExecutor<S> {
self.staged_for_commit_state = Some(
transactional_state.stage(tx_executed_class_hashes, tx_visited_storage_entries),
);
let raw_tx_execution_info = serde_json::to_vec(&typed_tx_execution_info)?;
Ok((raw_tx_execution_info, py_bouncer_info))

Ok((tx_execution_info, py_bouncer_info))
}
Err(error) => {
transactional_state.abort();
Expand Down
Loading