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

Commit 0a664b3

Browse files
committed
Add a query version bit.
1 parent 726d32d commit 0a664b3

10 files changed

+246
-71
lines changed

Diff for: crates/blockifier/src/transaction/account_transaction.rs

+100-31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::cmp::min;
22

33
use cairo_vm::vm::runners::cairo_runner::ResourceTracker;
44
use itertools::concat;
5+
use num_bigint::BigUint;
56
use starknet_api::calldata;
67
use starknet_api::core::{ContractAddress, EntryPointSelector};
78
use starknet_api::deprecated_contract_class::EntryPointType;
@@ -10,6 +11,7 @@ use starknet_api::transaction::{
1011
Calldata, DeployAccountTransaction, Fee, InvokeTransaction, TransactionVersion,
1112
};
1213

14+
use super::transaction_utils::felt_to_biguint;
1315
use crate::abi::abi_utils::selector_from_name;
1416
use crate::abi::constants as abi_constants;
1517
use crate::block_context::BlockContext;
@@ -26,6 +28,7 @@ use crate::state::cached_state::{
2628
};
2729
use crate::state::state_api::{State, StateReader};
2830
use crate::transaction::constants;
31+
use crate::transaction::constants::QUERY_VERSION_BASE_BIT;
2932
use crate::transaction::errors::TransactionExecutionError;
3033
use crate::transaction::objects::{
3134
AccountTransactionContext, ResourcesMapping, TransactionExecutionInfo,
@@ -34,7 +37,7 @@ use crate::transaction::objects::{
3437
use crate::transaction::transaction_execution::Transaction;
3538
use crate::transaction::transaction_types::TransactionType;
3639
use crate::transaction::transaction_utils::{
37-
calculate_l1_gas_usage, calculate_tx_resources, update_remaining_gas,
40+
biguint_to_felt, calculate_l1_gas_usage, calculate_tx_resources, update_remaining_gas,
3841
};
3942
use crate::transaction::transactions::{DeclareTransaction, Executable, ExecutableTransaction};
4043

@@ -140,14 +143,33 @@ impl AccountTransaction {
140143
}
141144
}
142145

143-
fn get_account_transaction_context(&self) -> AccountTransactionContext {
146+
fn version(&self) -> TransactionVersion {
147+
match self {
148+
Self::Declare(tx) => tx.tx().version(),
149+
Self::DeployAccount(tx) => tx.version,
150+
Self::Invoke(tx) => match tx {
151+
InvokeTransaction::V0(_) => TransactionVersion(StarkFelt::from(0_u8)),
152+
InvokeTransaction::V1(_) => TransactionVersion(StarkFelt::from(1_u8)),
153+
},
154+
}
155+
}
156+
157+
fn get_account_transaction_context(&self, simulate: bool) -> AccountTransactionContext {
158+
let mut version = self.version();
159+
if simulate {
160+
let query_version_base = BigUint::from(2_u8).pow(QUERY_VERSION_BASE_BIT);
161+
let simulate_version = query_version_base + felt_to_biguint(version.0);
162+
version = TransactionVersion(
163+
biguint_to_felt(simulate_version).expect("The version should be a field element."),
164+
);
165+
}
144166
match self {
145167
Self::Declare(tx) => {
146168
let tx = &tx.tx();
147169
AccountTransactionContext {
148170
transaction_hash: tx.transaction_hash(),
149171
max_fee: tx.max_fee(),
150-
version: tx.version(),
172+
version,
151173
signature: tx.signature(),
152174
nonce: tx.nonce(),
153175
sender_address: tx.sender_address(),
@@ -156,26 +178,37 @@ impl AccountTransaction {
156178
Self::DeployAccount(tx) => AccountTransactionContext {
157179
transaction_hash: tx.transaction_hash,
158180
max_fee: tx.max_fee,
159-
version: tx.version,
181+
version,
160182
signature: tx.signature.clone(),
161183
nonce: tx.nonce,
162184
sender_address: tx.contract_address,
163185
},
164186
Self::Invoke(tx) => AccountTransactionContext {
165187
transaction_hash: tx.transaction_hash(),
166188
max_fee: tx.max_fee(),
167-
version: match tx {
168-
InvokeTransaction::V0(_) => TransactionVersion(StarkFelt::from(0_u8)),
169-
InvokeTransaction::V1(_) => TransactionVersion(StarkFelt::from(1_u8)),
170-
},
189+
version,
171190
signature: tx.signature(),
172191
nonce: tx.nonce(),
173192
sender_address: tx.sender_address(),
174193
},
175194
}
176195
}
177196

178-
fn verify_tx_version(&self, version: TransactionVersion) -> TransactionExecutionResult<()> {
197+
fn verify_tx_version(
198+
&self,
199+
version: TransactionVersion,
200+
simulate: bool,
201+
) -> TransactionExecutionResult<()> {
202+
let version = match simulate {
203+
true => {
204+
let query_version_base = BigUint::from(2_u8).pow(QUERY_VERSION_BASE_BIT);
205+
let version = felt_to_biguint(version.0) - query_version_base;
206+
TransactionVersion(
207+
biguint_to_felt(version).expect("The version should be a field element."),
208+
)
209+
}
210+
false => version,
211+
};
179212
let allowed_versions: Vec<TransactionVersion> = match self {
180213
// Support `Declare` of version 0 in order to allow bootstrapping of a new system.
181214
Self::Declare(_) => {
@@ -204,7 +237,7 @@ impl AccountTransaction {
204237
account_tx_context: &AccountTransactionContext,
205238
state: &mut dyn State,
206239
) -> TransactionExecutionResult<()> {
207-
if account_tx_context.version == TransactionVersion(StarkFelt::from(0_u8)) {
240+
if account_tx_context.is_v0() {
208241
return Ok(());
209242
}
210243

@@ -229,9 +262,10 @@ impl AccountTransaction {
229262
remaining_gas: &mut u64,
230263
block_context: &BlockContext,
231264
validate: bool,
265+
simulate: bool,
232266
) -> TransactionExecutionResult<Option<CallInfo>> {
233267
if validate {
234-
self.validate_tx(state, resources, remaining_gas, block_context)
268+
self.validate_tx(state, resources, remaining_gas, block_context, simulate)
235269
} else {
236270
Ok(None)
237271
}
@@ -243,8 +277,9 @@ impl AccountTransaction {
243277
resources: &mut ExecutionResources,
244278
remaining_gas: &mut u64,
245279
block_context: &BlockContext,
280+
simulate: bool,
246281
) -> TransactionExecutionResult<Option<CallInfo>> {
247-
let account_tx_context = self.get_account_transaction_context();
282+
let account_tx_context = self.get_account_transaction_context(simulate);
248283
let mut context =
249284
EntryPointExecutionContext::new_validate(block_context, &account_tx_context);
250285
if context.account_tx_context.is_v0() {
@@ -306,8 +341,9 @@ impl AccountTransaction {
306341
&self,
307342
state: &mut TransactionalState<'_, S>,
308343
block_context: &BlockContext,
344+
simulate: bool,
309345
) -> TransactionExecutionResult<()> {
310-
let account_tx_context = self.get_account_transaction_context();
346+
let account_tx_context = self.get_account_transaction_context(simulate);
311347
let max_fee = account_tx_context.max_fee;
312348

313349
// Check fee balance.
@@ -341,14 +377,15 @@ impl AccountTransaction {
341377
block_context: &BlockContext,
342378
actual_fee: Fee,
343379
charge_fee: bool,
380+
simulate: bool,
344381
) -> TransactionExecutionResult<Option<CallInfo>> {
345382
if !charge_fee || actual_fee == Fee(0) {
346383
// Fee charging is not enforced in some transaction simulations and tests.
347384
return Ok(None);
348385
}
349386

350387
// Charge fee.
351-
let account_tx_context = self.get_account_transaction_context();
388+
let account_tx_context = self.get_account_transaction_context(simulate);
352389
let fee_transfer_call_info =
353390
Self::execute_fee_transfer(state, block_context, account_tx_context, actual_fee)?;
354391

@@ -409,6 +446,7 @@ impl AccountTransaction {
409446
}
410447
}
411448

449+
#[allow(clippy::too_many_arguments)]
412450
fn run_non_revertible<S: StateReader>(
413451
&self,
414452
state: &mut TransactionalState<'_, S>,
@@ -417,24 +455,37 @@ impl AccountTransaction {
417455
block_context: &BlockContext,
418456
mut execution_context: EntryPointExecutionContext,
419457
validate: bool,
458+
simulate: bool,
420459
) -> TransactionExecutionResult<ValidateExecuteCallInfo> {
421460
let validate_call_info: Option<CallInfo>;
422461
let execute_call_info: Option<CallInfo>;
423462
if matches!(self, Self::DeployAccount(_)) {
424463
// Handle `DeployAccount` transactions separately, due to different order of things.
425464
execute_call_info =
426465
self.run_execute(state, resources, &mut execution_context, remaining_gas)?;
427-
validate_call_info =
428-
self.handle_validate_tx(state, resources, remaining_gas, block_context, validate)?;
466+
validate_call_info = self.handle_validate_tx(
467+
state,
468+
resources,
469+
remaining_gas,
470+
block_context,
471+
validate,
472+
simulate,
473+
)?;
429474
} else {
430-
validate_call_info =
431-
self.handle_validate_tx(state, resources, remaining_gas, block_context, validate)?;
475+
validate_call_info = self.handle_validate_tx(
476+
state,
477+
resources,
478+
remaining_gas,
479+
block_context,
480+
validate,
481+
simulate,
482+
)?;
432483
execute_call_info =
433484
self.run_execute(state, resources, &mut execution_context, remaining_gas)?;
434485
}
435486
let state_changes = state.get_actual_state_changes_for_fee_charge(
436487
block_context.fee_token_address,
437-
Some(self.get_account_transaction_context().sender_address),
488+
Some(self.get_account_transaction_context(simulate).sender_address),
438489
)?;
439490
let (actual_fee, actual_resources) = self.calculate_actual_fee_and_resources(
440491
StateChangesCount::from(&state_changes),
@@ -444,6 +495,7 @@ impl AccountTransaction {
444495
block_context,
445496
false,
446497
0,
498+
simulate,
447499
)?;
448500
Ok(ValidateExecuteCallInfo::new_accepted(
449501
validate_call_info,
@@ -463,11 +515,18 @@ impl AccountTransaction {
463515
mut execution_context: EntryPointExecutionContext,
464516
charge_fee: bool,
465517
validate: bool,
518+
simulate: bool,
466519
) -> TransactionExecutionResult<ValidateExecuteCallInfo> {
467-
let account_tx_context = self.get_account_transaction_context();
520+
let account_tx_context = self.get_account_transaction_context(simulate);
468521
// Run the validation, and if execution later fails, only keep the validation diff.
469-
let validate_call_info =
470-
self.handle_validate_tx(state, resources, remaining_gas, block_context, validate)?;
522+
let validate_call_info = self.handle_validate_tx(
523+
state,
524+
resources,
525+
remaining_gas,
526+
block_context,
527+
validate,
528+
simulate,
529+
)?;
471530
let validate_steps = if validate {
472531
validate_call_info
473532
.as_ref()
@@ -535,6 +594,7 @@ impl AccountTransaction {
535594
block_context,
536595
false,
537596
0,
597+
simulate,
538598
)?;
539599

540600
// Check if as a result of tx execution the sender's fee token balance is maxed out,
@@ -576,6 +636,7 @@ impl AccountTransaction {
576636
block_context,
577637
true,
578638
n_reverted_steps,
639+
simulate,
579640
)?;
580641

581642
return Ok(ValidateExecuteCallInfo::new_reverted(
@@ -614,6 +675,7 @@ impl AccountTransaction {
614675
block_context,
615676
true,
616677
n_reverted_steps,
678+
simulate,
617679
)?;
618680

619681
Ok(ValidateExecuteCallInfo::new_reverted(
@@ -626,20 +688,21 @@ impl AccountTransaction {
626688
}
627689
}
628690

629-
fn is_non_revertible(&self) -> bool {
691+
fn is_non_revertible(&self, simulate: bool) -> bool {
630692
// Reverting a Declare or Deploy transaction is not currently supported in the OS.
631693
match self {
632694
Self::Declare(_) => true,
633695
Self::DeployAccount(_) => true,
634696
Self::Invoke(_) => {
635697
// V0 transactions do not have validation; we cannot deduct fee for execution. Thus,
636698
// invoke transactions of are non-revertible iff they are of version 0.
637-
self.get_account_transaction_context().is_v0()
699+
self.get_account_transaction_context(simulate).is_v0()
638700
}
639701
}
640702
}
641703

642704
/// Runs validation and execution.
705+
#[allow(clippy::too_many_arguments)]
643706
fn run_or_revert<S: StateReader>(
644707
&self,
645708
state: &mut TransactionalState<'_, S>,
@@ -648,8 +711,9 @@ impl AccountTransaction {
648711
block_context: &BlockContext,
649712
charge_fee: bool,
650713
validate: bool,
714+
simulate: bool,
651715
) -> TransactionExecutionResult<ValidateExecuteCallInfo> {
652-
let account_tx_context = self.get_account_transaction_context();
716+
let account_tx_context = self.get_account_transaction_context(simulate);
653717
let execution_context = if matches!(self, Self::DeployAccount(_)) {
654718
// Run constructor in validate mode, since it is executed before the transaction is
655719
// validated.
@@ -658,14 +722,15 @@ impl AccountTransaction {
658722
EntryPointExecutionContext::new_invoke(block_context, &account_tx_context)
659723
};
660724

661-
if self.is_non_revertible() {
725+
if self.is_non_revertible(simulate) {
662726
return self.run_non_revertible(
663727
state,
664728
resources,
665729
remaining_gas,
666730
block_context,
667731
execution_context,
668732
validate,
733+
simulate,
669734
);
670735
}
671736

@@ -677,6 +742,7 @@ impl AccountTransaction {
677742
execution_context,
678743
charge_fee,
679744
validate,
745+
simulate,
680746
)
681747
}
682748

@@ -690,8 +756,9 @@ impl AccountTransaction {
690756
block_context: &BlockContext,
691757
is_reverted: bool,
692758
n_reverted_steps: usize,
759+
simulate: bool,
693760
) -> TransactionExecutionResult<(Fee, ResourcesMapping)> {
694-
let account_tx_context = self.get_account_transaction_context();
761+
let account_tx_context = self.get_account_transaction_context(simulate);
695762

696763
let non_optional_call_infos = vec![validate_call_info.as_ref(), execute_call_info.as_ref()]
697764
.into_iter()
@@ -724,16 +791,17 @@ impl<S: StateReader> ExecutableTransaction<S> for AccountTransaction {
724791
block_context: &BlockContext,
725792
charge_fee: bool,
726793
validate: bool,
794+
simulate: bool,
727795
) -> TransactionExecutionResult<TransactionExecutionInfo> {
728-
let account_tx_context = self.get_account_transaction_context();
729-
self.verify_tx_version(account_tx_context.version)?;
796+
let account_tx_context = self.get_account_transaction_context(simulate);
797+
self.verify_tx_version(account_tx_context.version, simulate)?;
730798

731799
let mut resources = ExecutionResources::default();
732800
let mut remaining_gas = Transaction::initial_gas();
733801

734802
// Nonce and fee check should be done before running user code.
735803
if charge_fee {
736-
self.check_fee_balance(state, block_context)?;
804+
self.check_fee_balance(state, block_context, simulate)?;
737805
}
738806
// Handle nonce.
739807
Self::handle_nonce(&account_tx_context, state)?;
@@ -752,10 +820,11 @@ impl<S: StateReader> ExecutableTransaction<S> for AccountTransaction {
752820
block_context,
753821
charge_fee,
754822
validate,
823+
simulate,
755824
)?;
756825

757826
let fee_transfer_call_info =
758-
self.handle_fee(state, block_context, final_fee, charge_fee)?;
827+
self.handle_fee(state, block_context, final_fee, charge_fee, simulate)?;
759828

760829
let tx_execution_info = TransactionExecutionInfo {
761830
validate_call_info,

0 commit comments

Comments
 (0)