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

Add skip_nonce_check field to DeclareV2, Declare & DeployAccount txs #1135

Merged
merged 11 commits into from
Nov 10, 2023
64 changes: 61 additions & 3 deletions rpc_state_reader/tests/sir_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub fn execute_tx_configurable(
SNTransaction::DeployAccount(tx) => {
DeployAccount::from_sn_api_transaction(tx, chain_id.to_felt())
.unwrap()
.create_for_simulation(skip_validate, false, false, false)
.create_for_simulation(skip_validate, false, false, false, skip_nonce_check)
}
SNTransaction::Declare(tx) => {
// Fetch the contract_class from the next block (as we don't have it in the previous one)
Expand Down Expand Up @@ -180,7 +180,7 @@ pub fn execute_tx_configurable(
tx.class_hash().0.bytes().try_into().unwrap(),
)
.unwrap();
declare.create_for_simulation(skip_validate, false, false, false)
declare.create_for_simulation(skip_validate, false, false, false, skip_nonce_check)
} else {
let contract_class = match contract_class {
CompiledClass::Casm(cc) => cc.as_ref().clone(),
Expand All @@ -206,7 +206,7 @@ pub fn execute_tx_configurable(
Felt252::from_bytes_be(tx_hash.0.bytes()),
)
.unwrap();
declare.create_for_simulation(skip_validate, false, false, false)
declare.create_for_simulation(skip_validate, false, false, false, skip_nonce_check)
}
}
SNTransaction::L1Handler(tx) => L1Handler::from_sn_api_tx(
Expand Down Expand Up @@ -553,3 +553,61 @@ fn starknet_in_rust_test_case_declare_tx(hash: &str, block_number: u64, chain: R
}
}
}

#[test_case(
"0x05dc2a26a65b0fc9e8cb17d8b3e9142abdb2b2d2dd2f3eb275256f23bddfc9f2",
899787, // real block 899788
RpcChain::TestNet
)]
fn starknet_in_rust_test_case_tx_skip_nonce_check(hash: &str, block_number: u64, chain: RpcChain) {
let (tx_info, trace, receipt) =
execute_tx_configurable(hash, chain, BlockNumber(block_number), false, true);

let TransactionExecutionInfo {
call_info,
actual_fee,
..
} = tx_info;
let CallInfo {
execution_resources,
internal_calls,
..
} = call_info.unwrap();

// check Cairo VM execution resources
assert_eq_sorted!(
execution_resources.as_ref(),
Some(
&trace
.function_invocation
.as_ref()
.unwrap()
.execution_resources
),
"execution resources mismatch"
);

// check amount of internal calls
assert_eq!(
internal_calls.len(),
trace
.function_invocation
.as_ref()
.unwrap()
.internal_calls
.len(),
"internal calls length mismatch"
);

// check actual fee calculation
if receipt.actual_fee != actual_fee {
let diff = 100 * receipt.actual_fee.abs_diff(actual_fee) / receipt.actual_fee;

if diff >= 5 {
assert_eq!(
actual_fee, receipt.actual_fee,
"actual_fee mismatch differs from the baseline by more than 5% ({diff}%)",
);
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ mod test {
skip_execute: false,
skip_fee_transfer: false,
skip_validate: false,
skip_nonce_check: false,
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/transaction/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub struct Declare {
pub skip_validate: bool,
pub skip_execute: bool,
pub skip_fee_transfer: bool,
pub skip_nonce_check: bool,
}

// ------------------------------------------------------------
Expand Down Expand Up @@ -93,6 +94,7 @@ impl Declare {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
};

Ok(internal_declare)
Expand Down Expand Up @@ -128,6 +130,7 @@ impl Declare {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
};

Ok(internal_declare)
Expand All @@ -144,6 +147,7 @@ impl Declare {
hash_value: Felt252,
class_hash: ClassHash,
) -> Result<Self, TransactionError> {
let version = get_tx_version(version);
let validate_entry_point_selector = VALIDATE_DECLARE_ENTRY_POINT_SELECTOR.clone();

let internal_declare = Declare {
Expand All @@ -159,6 +163,7 @@ impl Declare {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
};

Ok(internal_declare)
Expand Down Expand Up @@ -268,7 +273,7 @@ impl Declare {

let contract_address = &self.sender_address;
let current_nonce = state.get_nonce_at(contract_address)?;
if current_nonce != self.nonce {
if current_nonce != self.nonce && !self.skip_nonce_check {
return Err(TransactionError::InvalidTransactionNonce(
current_nonce.to_string(),
self.nonce.to_string(),
Expand Down Expand Up @@ -332,6 +337,7 @@ impl Declare {
skip_execute: bool,
skip_fee_transfer: bool,
ignore_max_fee: bool,
skip_nonce_check: bool,
) -> Transaction {
let tx = Declare {
skip_validate,
Expand All @@ -343,6 +349,7 @@ impl Declare {
} else {
self.max_fee
},
skip_nonce_check,
..self.clone()
};

Expand Down Expand Up @@ -822,7 +829,7 @@ mod tests {

let simulate_declare = declare
.clone()
.create_for_simulation(true, false, true, false);
.create_for_simulation(true, false, true, false, false);

// ---------------------
// Comparison
Expand Down
6 changes: 5 additions & 1 deletion src/transaction/declare_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub struct DeclareV2 {
pub skip_validate: bool,
pub skip_execute: bool,
pub skip_fee_transfer: bool,
pub skip_nonce_check: bool,
}

impl DeclareV2 {
Expand Down Expand Up @@ -147,6 +148,7 @@ impl DeclareV2 {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
};

Ok(internal_declare)
Expand Down Expand Up @@ -268,7 +270,7 @@ impl DeclareV2 {
fn handle_nonce<S: State + StateReader>(&self, state: &mut S) -> Result<(), TransactionError> {
let contract_address = &self.sender_address;
let current_nonce = state.get_nonce_at(contract_address)?;
if current_nonce != self.nonce {
if current_nonce != self.nonce && !self.skip_nonce_check {
return Err(TransactionError::InvalidTransactionNonce(
current_nonce.to_string(),
self.nonce.to_string(),
Expand Down Expand Up @@ -468,6 +470,7 @@ impl DeclareV2 {
skip_execute: bool,
skip_fee_transfer: bool,
ignore_max_fee: bool,
skip_nonce_check: bool,
) -> Transaction {
let tx = DeclareV2 {
skip_validate,
Expand All @@ -478,6 +481,7 @@ impl DeclareV2 {
} else {
self.max_fee
},
skip_nonce_check,
..self.clone()
};

Expand Down
8 changes: 7 additions & 1 deletion src/transaction/deploy_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub struct DeployAccount {
skip_validate: bool,
skip_execute: bool,
skip_fee_transfer: bool,
skip_nonce_check: bool,
}

impl DeployAccount {
Expand Down Expand Up @@ -110,6 +111,7 @@ impl DeployAccount {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
})
}

Expand All @@ -124,6 +126,7 @@ impl DeployAccount {
contract_address_salt: Felt252,
hash_value: Felt252,
) -> Result<Self, SyscallHandlerError> {
let version = get_tx_version(version);
let contract_address = Address(calculate_contract_address(
&contract_address_salt,
&Felt252::from_bytes_be(&class_hash),
Expand All @@ -144,6 +147,7 @@ impl DeployAccount {
skip_execute: false,
skip_validate: false,
skip_fee_transfer: false,
skip_nonce_check: false,
})
}

Expand Down Expand Up @@ -307,7 +311,7 @@ impl DeployAccount {

// In blockifier, get_nonce_at returns zero if no entry is found.
let current_nonce = state.get_nonce_at(&self.contract_address)?;
if current_nonce != self.nonce {
if current_nonce != self.nonce && !self.skip_nonce_check {
return Err(TransactionError::InvalidTransactionNonce(
current_nonce.to_string(),
self.nonce.to_string(),
Expand Down Expand Up @@ -429,6 +433,7 @@ impl DeployAccount {
skip_execute: bool,
skip_fee_transfer: bool,
ignore_max_fee: bool,
skip_nonce_check: bool,
) -> Transaction {
let tx = DeployAccount {
skip_validate,
Expand All @@ -439,6 +444,7 @@ impl DeployAccount {
} else {
self.max_fee
},
skip_nonce_check,
..self.clone()
};

Expand Down
6 changes: 2 additions & 4 deletions src/transaction/invoke_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,7 @@ impl InvokeFunction {
vec![0, 1],
));
}
if !self.skip_nonce_check {
self.handle_nonce(state)?;
}
self.handle_nonce(state)?;

let mut transactional_state = state.create_transactional();
let mut tx_exec_info =
Expand Down Expand Up @@ -393,7 +391,7 @@ impl InvokeFunction {
Ok(())
}
Some(nonce) => {
if nonce != &current_nonce {
if !self.skip_nonce_check && nonce != &current_nonce {
return Err(TransactionError::InvalidTransactionNonce(
current_nonce.to_string(),
nonce.to_string(),
Expand Down
3 changes: 3 additions & 0 deletions src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ impl Transaction {
skip_execute,
skip_fee_transfer,
ignore_max_fee,
skip_nonce_check,
),
Transaction::DeclareV2(tx) => tx.create_for_simulation(
skip_validate,
skip_execute,
skip_fee_transfer,
ignore_max_fee,
skip_nonce_check,
),
Transaction::Deploy(tx) => {
tx.create_for_simulation(skip_validate, skip_execute, skip_fee_transfer)
Expand All @@ -119,6 +121,7 @@ impl Transaction {
skip_execute,
skip_fee_transfer,
ignore_max_fee,
skip_nonce_check,
),
Transaction::InvokeFunction(tx) => tx.create_for_simulation(
skip_validate,
Expand Down
2 changes: 2 additions & 0 deletions tests/internals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ fn declare_tx() -> Declare {
skip_execute: false,
skip_fee_transfer: false,
skip_validate: false,
skip_nonce_check: false,
}
}

Expand Down Expand Up @@ -782,6 +783,7 @@ fn declarev2_tx() -> DeclareV2 {
skip_execute: false,
skip_fee_transfer: false,
skip_validate: false,
skip_nonce_check: false,
}
}

Expand Down