Skip to content

Commit a3e390d

Browse files
blockifier: clean get_execution_info syscall test (#11355)
1 parent e5effa2 commit a3e390d

File tree

1 file changed

+118
-131
lines changed

1 file changed

+118
-131
lines changed

crates/blockifier/src/execution/syscalls/syscall_tests/get_execution_info.rs

Lines changed: 118 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -303,31 +303,48 @@ use crate::transaction::test_utils::proof_facts_as_cairo_array;
303303
false,
304304
true;
305305
"Exclude l1 data gas: query")]
306+
/// Tests the `get_execution_info` syscall by invoking `test_get_execution_info` across multiple
307+
/// contract implementations and transaction variants.
308+
///
309+
/// Contracts covered:
310+
/// - `TestContract` (Cairo 1): uses `get_execution_info_v3_syscall()`, expects V3 `TxInfo`.
311+
/// - `SierraExecutionInfoV1Contract` (Cairo 1): uses `get_execution_info_syscall()`, expects V1
312+
/// `TxInfo`.
313+
/// - `LegacyTestContract` (Cairo 0, compiler v2.1.0): uses `get_execution_info()`, expects V1
314+
/// `TxInfo`.
315+
///
316+
/// The test matrix varies execution mode (`Validate` vs `Execute`), tx version (V1 vs V3),
317+
/// query mode, and special account behaviors (v1-bound / data-gas / high-tip).
318+
/// In `Validate`, block info fields are rounded/zeroed; in `Execute`, they are populated normally.
319+
306320
fn test_get_execution_info(
307321
test_contract: FeatureContract,
308322
execution_mode: ExecutionMode,
309-
mut version: TransactionVersion,
323+
version: TransactionVersion,
310324
only_query: bool,
311325
v1_bound_account: bool,
312326
// Whether the tip is larger than `v1_bound_accounts_max_tip`.
313327
high_tip: bool,
314328
exclude_l1_data_gas: bool,
315329
) {
316330
let mut test_contract_data: FeatureContractData = test_contract.into();
331+
332+
// Override class hash for special account types that affect execution info behavior.
317333
if v1_bound_account {
318334
assert!(
319335
!exclude_l1_data_gas,
320336
"Unable to set both exclude_l1_data_gas and v1_bound_account."
321337
);
322-
let optional_class_hash =
323-
VersionedConstants::latest_constants().os_constants.v1_bound_accounts_cairo1.first();
324-
test_contract_data.class_hash =
325-
*optional_class_hash.expect("No v1 bound accounts found in versioned constants.");
338+
test_contract_data.class_hash = *VersionedConstants::latest_constants()
339+
.os_constants
340+
.v1_bound_accounts_cairo1
341+
.first()
342+
.expect("No v1 bound accounts found in versioned constants.");
326343
} else if exclude_l1_data_gas {
327344
test_contract_data.class_hash =
328345
*VersionedConstants::latest_constants().os_constants.data_gas_accounts.first().unwrap();
329346
}
330-
// Set the erc20 version to be the same as the test contract version.
347+
331348
let erc20_version = test_contract.cairo_version();
332349
let state = &mut test_state_inner(
333350
&ChainInfo::create_for_testing(),
@@ -336,6 +353,8 @@ fn test_get_execution_info(
336353
&HashVersion::V2,
337354
erc20_version,
338355
);
356+
357+
// Build expected block info.
339358
let expected_block_info = match execution_mode {
340359
ExecutionMode::Validate => [
341360
// Rounded block number.
@@ -351,56 +370,15 @@ fn test_get_execution_info(
351370
],
352371
};
353372

373+
// Build transaction fields.
354374
let test_contract_address = test_contract.get_instance_address(0);
355-
356-
// Transaction tip.
357-
let tip = Tip(VersionedConstants::latest_constants().os_constants.v1_bound_accounts_max_tip.0
358-
+ if high_tip { 1 } else { 0 });
359-
let expected_tip = if version == TransactionVersion::THREE { tip } else { Tip(0) };
360-
361375
let tx_hash = tx_hash!(1991);
362-
363-
let (expected_unsupported_fields, expected_signature) = match test_contract {
364-
FeatureContract::LegacyTestContract => {
365-
// Read and parse file content.
366-
let raw_contract: serde_json::Value =
367-
serde_json::from_str(&test_contract.get_raw_class()).expect("Error parsing JSON");
368-
// Verify version.
369-
if let Some(compiler_version) = raw_contract["compiler_version"].as_str() {
370-
assert_eq!(compiler_version, "2.1.0");
371-
} else {
372-
panic!("'compiler_version' not found or not a valid string in JSON.");
373-
};
374-
(vec![], vec![])
375-
}
376-
#[cfg(feature = "cairo_native")]
377-
FeatureContract::SierraExecutionInfoV1Contract(RunnableCairo1::Native) => (vec![], vec![]),
378-
_ => {
379-
(
380-
vec![
381-
expected_tip.into(), // Tip.
382-
Felt::ZERO, // Paymaster data.
383-
Felt::ZERO, // Nonce DA.
384-
Felt::ZERO, // Fee DA.
385-
Felt::ZERO, // Account data.
386-
],
387-
vec![tx_hash.0],
388-
)
389-
}
390-
};
391-
392-
let mut expected_version = if v1_bound_account && !high_tip { 1.into() } else { version.0 };
393-
if only_query {
394-
let simulate_version_base = *QUERY_VERSION_BASE;
395-
let query_version = simulate_version_base + version.0;
396-
version = TransactionVersion(query_version);
397-
expected_version += simulate_version_base;
398-
}
399-
400-
let max_fee = Fee(42);
376+
let max_fee = if version == TransactionVersion::ONE { Fee(42) } else { Fee(0) };
401377
let nonce = nonce!(3_u16);
402378
let sender_address = test_contract_address;
403-
let signature = TransactionSignature(Arc::new(expected_signature));
379+
let tip = Tip(VersionedConstants::latest_constants().os_constants.v1_bound_accounts_max_tip.0
380+
+ if high_tip { 1 } else { 0 });
381+
let expected_tip = if version == TransactionVersion::THREE { tip } else { Tip(0) };
404382

405383
let resource_bounds =
406384
ResourceBounds { max_amount: GasAmount(13), max_price_per_unit: GasPrice(61) };
@@ -410,116 +388,125 @@ fn test_get_execution_info(
410388
l1_data_gas: resource_bounds,
411389
});
412390

413-
let expected_resource_bounds: Vec<Felt> = match (test_contract, version) {
414-
(FeatureContract::LegacyTestContract, _) => vec![],
391+
// Sanity check: verify legacy contract has expected compiler version.
392+
if matches!(test_contract, FeatureContract::LegacyTestContract) {
393+
let raw_contract: serde_json::Value =
394+
serde_json::from_str(&test_contract.get_raw_class()).expect("Error parsing JSON");
395+
let compiler_version = raw_contract["compiler_version"]
396+
.as_str()
397+
.expect("'compiler_version' not found or not a valid string in JSON.");
398+
assert_eq!(compiler_version, "2.1.0");
399+
}
400+
401+
let expected_signature = match test_contract {
402+
FeatureContract::LegacyTestContract => vec![],
415403
#[cfg(feature = "cairo_native")]
416-
(FeatureContract::SierraExecutionInfoV1Contract(RunnableCairo1::Native), _) => vec![],
417-
(_, version) if version == TransactionVersion::ONE => vec![
418-
felt!(0_u16), // Length of resource bounds array.
419-
],
420-
(_, _) => {
421-
vec![felt!(if exclude_l1_data_gas { 2_u8 } else { 3_u8 })] // Length of resource bounds array.
422-
.into_iter()
423-
.chain(
424-
valid_resource_bounds_as_felts(&all_resource_bounds, exclude_l1_data_gas)
425-
.unwrap()
426-
.into_iter()
427-
.flat_map(|bounds| bounds.flatten()),
428-
)
429-
.collect()
430-
}
404+
FeatureContract::SierraExecutionInfoV1Contract(RunnableCairo1::Native) => vec![],
405+
FeatureContract::TestContract(_) => vec![tx_hash.0],
406+
_ => panic!("Unsupported contract for this test."),
431407
};
408+
let signature = TransactionSignature(Arc::new(expected_signature));
432409

433-
// Only transaction V3 supports non-trivial proof facts.
434-
// TODO(Meshi): Make sure we do not change the version or the transaction.
435-
let proof_facts = if version == TransactionVersion::ONE {
436-
ProofFacts::default()
437-
} else {
410+
let mut expected_version = if v1_bound_account && !high_tip { 1.into() } else { version.0 };
411+
if only_query {
412+
expected_version += *QUERY_VERSION_BASE;
413+
}
414+
415+
// Only V3 transactions support non-trivial proof facts.
416+
let proof_facts = if version == TransactionVersion::THREE {
438417
ProofFacts::snos_proof_facts_for_testing()
418+
} else {
419+
ProofFacts::default()
439420
};
440421

441-
let expected_tx_info: Vec<Felt>;
442-
let tx_info: TransactionInfo;
443-
if version == TransactionVersion::ONE {
444-
expected_tx_info = vec![
445-
expected_version, // Transaction version.
446-
*sender_address.0.key(), // Account address.
447-
felt!(max_fee.0), // Max fee.
448-
Felt::ZERO, // Signature.
449-
tx_hash.0, // Transaction hash.
450-
felt!(&*CHAIN_ID_FOR_TESTS.as_hex()), // Chain ID.
451-
nonce.0, // Nonce.
452-
];
422+
// Build transaction info object.
423+
let common_fields = CommonAccountFields {
424+
transaction_hash: tx_hash,
425+
version,
426+
signature,
427+
nonce,
428+
sender_address,
429+
only_query,
430+
};
453431

454-
tx_info = TransactionInfo::Deprecated(DeprecatedTransactionInfo {
455-
common_fields: CommonAccountFields {
456-
transaction_hash: tx_hash,
457-
version: TransactionVersion::ONE,
458-
signature,
459-
nonce,
460-
sender_address,
461-
only_query,
462-
},
463-
max_fee,
464-
});
432+
let tx_info = if version == TransactionVersion::ONE {
433+
TransactionInfo::Deprecated(DeprecatedTransactionInfo { common_fields, max_fee })
465434
} else {
466-
expected_tx_info = vec![
467-
expected_version, // Transaction version.
468-
*sender_address.0.key(), // Account address.
469-
Felt::ZERO, // Max fee.
470-
Felt::ZERO, // Signature.
471-
tx_hash.0, // Transaction hash.
472-
felt!(&*CHAIN_ID_FOR_TESTS.as_hex()), // Chain ID.
473-
nonce.0, // Nonce.
474-
];
475-
476-
tx_info = TransactionInfo::Current(CurrentTransactionInfo {
477-
common_fields: CommonAccountFields {
478-
transaction_hash: tx_hash,
479-
version: TransactionVersion::THREE,
480-
signature,
481-
nonce,
482-
sender_address,
483-
only_query,
484-
},
435+
TransactionInfo::Current(CurrentTransactionInfo {
436+
common_fields,
485437
resource_bounds: all_resource_bounds,
486438
tip,
487439
nonce_data_availability_mode: DataAvailabilityMode::L1,
488440
fee_data_availability_mode: DataAvailabilityMode::L1,
489441
paymaster_data: PaymasterData::default(),
490442
account_deployment_data: AccountDeploymentData::default(),
491443
proof_facts: proof_facts.clone(),
492-
});
493-
}
444+
})
445+
};
494446

447+
// Build expected calldata to pass to the contract's test_get_execution_info entry point.
448+
// The contract will compare the syscall results with the expected values.
495449
let entry_point_selector = selector_from_name("test_get_execution_info");
450+
496451
let expected_call_info = vec![
497-
felt!(0_u16), // Caller address.
498-
*test_contract_address.0.key(), // Storage address.
499-
entry_point_selector.0, // Entry point selector.
452+
felt!(0_u16), // Caller address.
453+
*test_contract_address.0.key(),
454+
entry_point_selector.0,
500455
];
501456

502-
let expected_proof_facts = proof_facts_as_cairo_array(proof_facts);
503-
let mut calldata = vec![
504-
expected_block_info.to_vec(),
505-
expected_call_info,
506-
expected_tx_info,
507-
expected_resource_bounds.into_iter().chain(expected_unsupported_fields).collect(),
457+
// TxInfo fields (shared between V1 and V3).
458+
let expected_tx_info = vec![
459+
expected_version,
460+
*sender_address.0.key(),
461+
felt!(max_fee.0),
462+
Felt::ZERO, // Signature
463+
tx_hash.0,
464+
felt!(&*CHAIN_ID_FOR_TESTS.as_hex()),
465+
nonce.0,
508466
];
509467

510-
// Only `TestContract` was updated to call the `get_execution_info_v3` that includes
511-
// `proof_facts`. The other contracts continue to call `get_execution_info_v1`, so their
512-
// calldata layout must remain unchanged.
468+
let mut calldata = vec![expected_block_info.to_vec(), expected_call_info, expected_tx_info];
469+
470+
// TestContract uses get_execution_info_v3 which includes additional V3 fields.
471+
// The LegacyTestContract and SierraExecutionInfoV1Contract use get_execution_info_v1 and don't
472+
// expect these fields.
513473
if matches!(test_contract, FeatureContract::TestContract(_)) {
514-
calldata.push(expected_proof_facts);
474+
let expected_resource_bounds: Vec<Felt> = if version == TransactionVersion::ONE {
475+
vec![felt!(0_u16)] // Empty resource bounds for V1.
476+
} else {
477+
let num_resources = if exclude_l1_data_gas { 2_u8 } else { 3_u8 };
478+
std::iter::once(felt!(num_resources))
479+
.chain(
480+
valid_resource_bounds_as_felts(&all_resource_bounds, exclude_l1_data_gas)
481+
.unwrap()
482+
.into_iter()
483+
.flat_map(|bounds| bounds.flatten()),
484+
)
485+
.collect()
486+
};
487+
488+
let expected_unsupported_fields = vec![
489+
expected_tip.into(),
490+
Felt::ZERO, // Paymaster data.
491+
Felt::ZERO, // Nonce DA mode.
492+
Felt::ZERO, // Fee DA mode.
493+
Felt::ZERO, // Account deployment data.
494+
];
495+
496+
calldata.push(
497+
expected_resource_bounds.into_iter().chain(expected_unsupported_fields).collect(),
498+
);
499+
calldata.push(proof_facts_as_cairo_array(proof_facts));
515500
}
516501

502+
// Execute and verify.
517503
let entry_point_call = CallEntryPoint {
518504
entry_point_selector,
519505
code_address: None,
520506
calldata: Calldata(calldata.concat().into()),
521507
..trivial_external_entry_point_with_address(test_contract_address)
522508
};
509+
523510
let result = entry_point_call.execute_directly_given_tx_info(
524511
state,
525512
tx_info,

0 commit comments

Comments
 (0)