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

Add a query version bit. #1042

Closed
wants to merge 1 commit into from
Closed
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
131 changes: 100 additions & 31 deletions crates/blockifier/src/transaction/account_transaction.rs

Large diffs are not rendered by default.

59 changes: 32 additions & 27 deletions crates/blockifier/src/transaction/account_transactions_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn create_test_init_data(
);

let account_tx = AccountTransaction::DeployAccount(deploy_account_tx);
account_tx.execute(&mut state, &block_context, true, true).unwrap();
account_tx.execute(&mut state, &block_context, true, true, false).unwrap();

// Declare a contract.
let contract_class = ContractClassV0::from_file(TEST_CONTRACT_CAIRO0_PATH).into();
Expand All @@ -116,7 +116,7 @@ fn create_test_init_data(
)
.unwrap(),
);
account_tx.execute(&mut state, &block_context, true, true).unwrap();
account_tx.execute(&mut state, &block_context, true, true, false).unwrap();

// Deploy a contract using syscall deploy.
let entry_point_selector = selector_from_name("deploy_contract");
Expand Down Expand Up @@ -171,13 +171,19 @@ fn test_fee_enforcement(

let account_tx = AccountTransaction::DeployAccount(deploy_account_tx);
let enforce_fee = account_tx.enforce_fee();
let result = account_tx.execute(&mut state, &block_context, true, true);
let result = account_tx.execute(&mut state, &block_context, true, true, false);
assert_eq!(result.is_err(), enforce_fee);
}
}

#[rstest]
fn test_account_flow_test(max_fee: Fee, #[from(create_test_init_data)] init_data: TestInitData) {
#[case(false)]
#[case(true)]
fn test_account_flow_test(
max_fee: Fee,
#[from(create_test_init_data)] init_data: TestInitData,
#[case] simulate: bool,
) {
let TestInitData {
mut state,
account_address,
Expand All @@ -188,20 +194,15 @@ fn test_account_flow_test(max_fee: Fee, #[from(create_test_init_data)] init_data

// Invoke a function from the newly deployed contract.
let entry_point_selector = selector_from_name("return_result");
run_invoke_tx(
calldata![
*contract_address.0.key(), // Contract address.
entry_point_selector.0, // EP selector.
stark_felt!(1_u8), // Calldata length.
stark_felt!(2_u8) // Calldata: num.
],
&mut state,
account_address,
&block_context,
&mut nonce_manager,
max_fee,
)
.unwrap();
let execute_calldata = calldata![
*contract_address.0.key(), // Contract address.
entry_point_selector.0, // EP selector.
stark_felt!(1_u8), // Calldata length.
stark_felt!(2_u8) // Calldata: num.
];
account_invoke_tx(execute_calldata, account_address, &mut nonce_manager, max_fee)
.execute(&mut state, &block_context, true, true, simulate)
.unwrap();
}

#[rstest]
Expand Down Expand Up @@ -306,7 +307,8 @@ fn test_revert_invoke(
);

let account_tx = AccountTransaction::DeployAccount(deploy_account_tx);
let deploy_execution_info = account_tx.execute(&mut state, &block_context, true, true).unwrap();
let deploy_execution_info =
account_tx.execute(&mut state, &block_context, true, true, false).unwrap();

// Invoke a function from the newly deployed contract, that changes the state.
let storage_key = stark_felt!(9_u8);
Expand Down Expand Up @@ -374,7 +376,7 @@ fn test_fail_deploy_account(block_context: BlockContext) {
&mut NonceManager::default(),
);
let deploy_address = deploy_account_tx.get_address_of_deploy().unwrap();
deploy_account_tx.execute(&mut state, &block_context, true, true).unwrap_err();
deploy_account_tx.execute(&mut state, &block_context, true, true, false).unwrap_err();

// Assert nonce and balance are unchanged, and that no contract was deployed at the address.
assert_eq!(state.get_nonce_at(deployed_account_address).unwrap(), Nonce(stark_felt!(0_u8)));
Expand Down Expand Up @@ -416,7 +418,7 @@ fn test_fail_declare(max_fee: Fee, #[from(create_test_init_data)] init_data: Tes
);

// Fail execution, assert nonce and balance are unchanged.
declare_account_tx.execute(&mut state, &block_context, true, true).unwrap_err();
declare_account_tx.execute(&mut state, &block_context, true, true, false).unwrap_err();
assert_eq!(state.get_nonce_at(account_address).unwrap(), next_nonce);
assert_eq!(
state.get_fee_token_balance(&block_context, &account_address).unwrap(),
Expand Down Expand Up @@ -670,6 +672,7 @@ fn test_max_fee_to_max_steps_conversion(
stark_felt!(1_u8), // Calldata length.
stark_felt!(25_u8) // Calldata: arg.
];
let simulate = false;

// First invocation of `with_arg` gets the exact pre-calculated actual fee as max_fee.
let account_tx1 = account_invoke_tx(
Expand All @@ -680,10 +683,11 @@ fn test_max_fee_to_max_steps_conversion(
);
let execution_context1 = EntryPointExecutionContext::new_invoke(
&block_context,
&account_tx1.get_account_transaction_context(),
&account_tx1.get_account_transaction_context(simulate),
);
let max_steps_limit1 = execution_context1.vm_run_resources.get_n_steps();
let tx_execution_info1 = account_tx1.execute(&mut state, &block_context, true, true).unwrap();
let tx_execution_info1 =
account_tx1.execute(&mut state, &block_context, true, true, simulate).unwrap();
let n_steps1 = tx_execution_info1.actual_resources.0.get("n_steps").unwrap();

// Second invocation of `with_arg` gets twice the pre-calculated actual fee as max_fee.
Expand All @@ -695,10 +699,11 @@ fn test_max_fee_to_max_steps_conversion(
);
let execution_context2 = EntryPointExecutionContext::new_invoke(
&block_context,
&account_tx2.get_account_transaction_context(),
&account_tx2.get_account_transaction_context(simulate),
);
let max_steps_limit2 = execution_context2.vm_run_resources.get_n_steps();
let tx_execution_info2 = account_tx2.execute(&mut state, &block_context, true, true).unwrap();
let tx_execution_info2 =
account_tx2.execute(&mut state, &block_context, true, true, simulate).unwrap();
let n_steps2 = tx_execution_info2.actual_resources.0.get("n_steps").unwrap();

// Test that steps limit doubles as max_fee doubles, but actual consumed steps and fee remains.
Expand Down Expand Up @@ -799,7 +804,7 @@ fn write_and_transfer(
*block_context.fee_token_address.0.key()
];
let account_tx = account_invoke_tx(execute_calldata, account_address, nonce_manager, max_fee);
account_tx.execute(state, block_context, true, true).unwrap()
account_tx.execute(state, block_context, true, true, false).unwrap()
}

/// Tests that when a transaction drains an account's balance before fee transfer, the execution is
Expand Down Expand Up @@ -845,7 +850,7 @@ fn test_revert_on_overdraft(
let approve_tx: AccountTransaction =
account_invoke_tx(approve_calldata, account_address, &mut nonce_manager, max_fee);
let approval_execution_info =
approve_tx.execute(&mut state, &block_context, true, true).unwrap();
approve_tx.execute(&mut state, &block_context, true, true, false).unwrap();
assert!(!approval_execution_info.is_reverted());

// Transfer a valid amount of funds to compute the cost of a successful
Expand Down
4 changes: 4 additions & 0 deletions crates/blockifier/src/transaction/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ pub const FELT_TRUE: u64 = 1;

// Expected return value of a `validate` entry point: `VALID`.
pub const VALIDATE_RETDATA: &str = "0x56414c4944";

// TODO(Noa, 14/11/2023): Replace SIMULATE_VERSION_BASE_BIT with a lazy calculation.
// pub static SIMULATE_VERSION_BASE: Lazy<BigUint> = ...
pub const SIMULATE_VERSION_BASE_BIT: u32 = 128;
8 changes: 8 additions & 0 deletions crates/blockifier/src/transaction/objects.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use std::collections::{HashMap, HashSet};

use itertools::concat;
use num_bigint::BigUint;
use starknet_api::core::{ClassHash, ContractAddress, Nonce};
use starknet_api::hash::StarkFelt;
use starknet_api::stark_felt;
use starknet_api::transaction::{Fee, TransactionHash, TransactionSignature, TransactionVersion};

use super::transaction_utils::biguint_to_felt;
use crate::execution::entry_point::CallInfo;
use crate::transaction::constants::SIMULATE_VERSION_BASE_BIT;
use crate::transaction::errors::TransactionExecutionError;

pub type TransactionExecutionResult<T> = Result<T, TransactionExecutionError>;
Expand All @@ -25,6 +28,11 @@ pub struct AccountTransactionContext {
impl AccountTransactionContext {
pub fn is_v0(&self) -> bool {
self.version == TransactionVersion(stark_felt!(0_u8))
|| self.version
== TransactionVersion(
biguint_to_felt(BigUint::from(2_u8).pow(SIMULATE_VERSION_BASE_BIT))
.expect("`SIMULATE_VERSION_BASE should` be a valid TransactionVersion"),
)
}
}

Expand Down
7 changes: 6 additions & 1 deletion crates/blockifier/src/transaction/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn create_account_tx_test_state(
account_address: &str,
erc20_account_balance_key: StorageKey,
initial_account_balance: u128,
test_contract_class: ContractClass,
) -> CachedState<DictStateReader> {
let block_context = BlockContext::create_for_testing();

Expand All @@ -47,7 +48,7 @@ pub fn create_account_tx_test_state(
(test_account_class_hash, account_class),
// TODO(Mohammad,01/08/2023): Use Cairo 1 test contract when running Cairo 1 account
// contract.
(test_contract_class_hash, ContractClassV0::from_file(TEST_CONTRACT_CAIRO0_PATH).into()),
(test_contract_class_hash, test_contract_class),
(test_erc20_class_hash, ContractClassV0::from_file(ERC20_CONTRACT_PATH).into()),
]);
let test_contract_address = ContractAddress(patricia_key!(TEST_CONTRACT_ADDRESS));
Expand Down Expand Up @@ -83,6 +84,7 @@ pub fn create_state_with_trivial_validation_account() -> CachedState<DictStateRe
TEST_ACCOUNT_CONTRACT_ADDRESS,
test_erc20_account_balance_key(),
account_balance,
ContractClassV0::from_file(TEST_CONTRACT_CAIRO0_PATH).into(),
)
}

Expand All @@ -94,6 +96,7 @@ pub fn create_state_with_cairo1_account() -> CachedState<DictStateReader> {
TEST_ACCOUNT_CONTRACT_ADDRESS,
test_erc20_account_balance_key(),
account_balance,
ContractClassV0::from_file(TEST_CONTRACT_CAIRO0_PATH).into(),
)
}

Expand All @@ -105,6 +108,7 @@ pub fn create_state_with_falliable_validation_account() -> CachedState<DictState
TEST_FAULTY_ACCOUNT_CONTRACT_ADDRESS,
test_erc20_faulty_account_balance_key(),
account_balance * 2,
ContractClassV0::from_file(TEST_CONTRACT_CAIRO0_PATH).into(),
)
}

Expand Down Expand Up @@ -196,5 +200,6 @@ pub fn run_invoke_tx(
block_context,
true,
true,
false,
)
}
6 changes: 4 additions & 2 deletions crates/blockifier/src/transaction/transaction_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl<S: StateReader> ExecutableTransaction<S> for L1HandlerTransaction {
block_context: &BlockContext,
_charge_fee: bool,
_validate: bool,
_simulate: bool,
) -> TransactionExecutionResult<TransactionExecutionInfo> {
let tx = &self.tx;
let tx_context = AccountTransactionContext {
Expand Down Expand Up @@ -124,13 +125,14 @@ impl<S: StateReader> ExecutableTransaction<S> for Transaction {
block_context: &BlockContext,
charge_fee: bool,
validate: bool,
simulate: bool,
) -> TransactionExecutionResult<TransactionExecutionInfo> {
match self {
Self::AccountTransaction(account_tx) => {
account_tx.execute_raw(state, block_context, charge_fee, validate)
account_tx.execute_raw(state, block_context, charge_fee, validate, simulate)
}
Self::L1HandlerTransaction(tx) => {
tx.execute_raw(state, block_context, charge_fee, validate)
tx.execute_raw(state, block_context, charge_fee, validate, simulate)
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions crates/blockifier/src/transaction/transaction_utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::collections::HashMap;

use cairo_vm::vm::runners::builtin_runner::SEGMENT_ARENA_BUILTIN_NAME;
use num_bigint::BigUint;
use starknet_api::hash::StarkFelt;

use crate::abi::constants;
use crate::execution::entry_point::{CallInfo, ExecutionResources};
Expand Down Expand Up @@ -62,3 +64,14 @@ pub fn calculate_tx_resources(
pub fn update_remaining_gas(remaining_gas: &mut u64, call_info: &CallInfo) {
*remaining_gas -= call_info.execution.gas_consumed;
}

// TODO: Convert to a `TryFrom` cast and put in starknet-api (In StarkFelt).
pub fn biguint_to_felt(biguint: BigUint) -> TransactionExecutionResult<StarkFelt> {
let biguint_hex = format!("{biguint:#x}");
Ok(StarkFelt::try_from(&*biguint_hex)?)
}

// TODO: Convert to a `Into` cast and put in starknet-api (In StarkFelt).
pub fn felt_to_biguint(felt: StarkFelt) -> BigUint {
BigUint::from_bytes_be(felt.bytes())
}
11 changes: 9 additions & 2 deletions crates/blockifier/src/transaction/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ pub trait ExecutableTransaction<S: StateReader>: Sized {
block_context: &BlockContext,
charge_fee: bool,
validate: bool,
simulate: bool,
) -> TransactionExecutionResult<TransactionExecutionInfo> {
log::debug!("Executing Transaction...");
let mut transactional_state = CachedState::create_transactional(state);
let execution_result =
self.execute_raw(&mut transactional_state, block_context, charge_fee, validate);
let execution_result = self.execute_raw(
&mut transactional_state,
block_context,
charge_fee,
validate,
simulate,
);

match execution_result {
Ok(value) => {
Expand All @@ -61,6 +67,7 @@ pub trait ExecutableTransaction<S: StateReader>: Sized {
block_context: &BlockContext,
charge_fee: bool,
validate: bool,
simulate: bool,
) -> TransactionExecutionResult<TransactionExecutionInfo>;
}

Expand Down
Loading