@@ -17,7 +17,7 @@ use starknet_api::abi::abi_utils::{
1717 get_storage_var_address,
1818 selector_from_name,
1919} ;
20- use starknet_api:: block:: { FeeType , GasPrice } ;
20+ use starknet_api:: block:: { BlockHash , BlockNumber , FeeType , GasPrice } ;
2121use starknet_api:: contract_class:: compiled_class_hash:: { HashVersion , HashableCompiledClass } ;
2222use starknet_api:: contract_class:: ContractClass ;
2323use starknet_api:: core:: {
@@ -41,6 +41,7 @@ use starknet_api::test_utils::deploy_account::executable_deploy_account_tx;
4141use starknet_api:: test_utils:: invoke:: { executable_invoke_tx, InvokeTxArgs } ;
4242use starknet_api:: test_utils:: {
4343 NonceManager ,
44+ CURRENT_BLOCK_NUMBER ,
4445 DEFAULT_L1_DATA_GAS_MAX_AMOUNT ,
4546 DEFAULT_L1_GAS_AMOUNT ,
4647 DEFAULT_L2_GAS_MAX_AMOUNT ,
@@ -55,9 +56,12 @@ use starknet_api::transaction::fields::{
5556 ContractAddressSalt ,
5657 Fee ,
5758 GasVectorComputationMode ,
59+ ProofFacts ,
5860 Resource ,
5961 ResourceBounds ,
62+ SnosProofFacts ,
6063 ValidResourceBounds ,
64+ VIRTUAL_SNOS ,
6165} ;
6266use starknet_api:: transaction:: {
6367 DeclareTransaction ,
@@ -79,6 +83,7 @@ use starknet_api::{
7983} ;
8084use starknet_types_core:: felt:: Felt ;
8185
86+ use crate :: abi:: constants:: STORED_BLOCK_HASH_BUFFER ;
8287use crate :: context:: { BlockContext , TransactionContext } ;
8388use crate :: execution:: call_info:: CallInfo ;
8489use crate :: execution:: contract_class:: TrackedResource ;
@@ -2191,3 +2196,96 @@ fn test_missing_validate_entrypoint_rejects(
21912196 if ret == retdata![ Felt :: from_hex( ENTRYPOINT_NOT_FOUND_ERROR ) . unwrap( ) ]
21922197 ) ;
21932198}
2199+
2200+ /// Converts SnosProofFacts to ProofFacts for testing.
2201+ fn snos_to_proof_facts ( snos : SnosProofFacts ) -> ProofFacts {
2202+ vec ! [
2203+ felt!( VIRTUAL_SNOS ) ,
2204+ snos. program_hash,
2205+ felt!( snos. block_number. 0 ) ,
2206+ snos. block_hash. 0 ,
2207+ snos. config_hash,
2208+ ]
2209+ . into ( )
2210+ }
2211+
2212+ /// Returns invalid proof_facts with a too recent block number (at the boundary).
2213+ fn proof_facts_with_too_recent_block ( ) -> ProofFacts {
2214+ let mut snos_proof_facts =
2215+ SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) ) . unwrap ( ) ;
2216+ // Set the proof block number to the first invalid value:
2217+ // `current_block_number - STORED_BLOCK_HASH_BUFFER`
2218+ // (i.e. last allowed block + 1).
2219+ snos_proof_facts. block_number = BlockNumber ( CURRENT_BLOCK_NUMBER - STORED_BLOCK_HASH_BUFFER ) ;
2220+ snos_to_proof_facts ( snos_proof_facts)
2221+ }
2222+
2223+ /// Returns invalid proof_facts with a mismatched block hash.
2224+ fn proof_facts_with_mismatched_hash ( ) -> ProofFacts {
2225+ let mut snos_proof_facts =
2226+ SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) ) . unwrap ( ) ;
2227+ snos_proof_facts. block_hash = BlockHash ( snos_proof_facts. block_hash . 0 + 1 ) ;
2228+ snos_to_proof_facts ( snos_proof_facts)
2229+ }
2230+
2231+ /// Returns invalid proof_facts with a zero block hash.
2232+ fn proof_facts_with_zero_block_hash ( ) -> ProofFacts {
2233+ let mut snos_proof_facts = SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) )
2234+ . expect ( "Invalid proof facts" ) ;
2235+ snos_proof_facts. block_hash = BlockHash ( Felt :: ZERO ) ;
2236+ snos_to_proof_facts ( snos_proof_facts)
2237+ }
2238+
2239+ /// Returns invalid proof_facts with an invalid program hash.
2240+ fn proof_facts_with_invalid_program_hash ( ) -> ProofFacts {
2241+ let mut snos_proof_facts = SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) )
2242+ . expect ( "Invalid proof facts" ) ;
2243+ snos_proof_facts. program_hash = Felt :: from ( 0x12345678_u64 ) ;
2244+ snos_to_proof_facts ( snos_proof_facts)
2245+ }
2246+
2247+ /// Tests the `validate_proof_facts` function for Invoke V3 transactions.
2248+ /// The test runs `perform_pre_validation_stage` and asserts that invalid cases
2249+ /// fail with `InvalidProofFacts`, while valid cases pass.
2250+ #[ rstest]
2251+ #[ case:: valid( ProofFacts :: snos_proof_facts_for_testing( ) , CURRENT_BLOCK_NUMBER , false ) ]
2252+ #[ case:: block_number_too_recent( proof_facts_with_too_recent_block( ) , CURRENT_BLOCK_NUMBER , true ) ]
2253+ #[ case:: current_block_number_too_small(
2254+ ProofFacts :: snos_proof_facts_for_testing( ) ,
2255+ STORED_BLOCK_HASH_BUFFER - 1 ,
2256+ true ,
2257+ ) ]
2258+ #[ case:: block_hash_mismatched( proof_facts_with_mismatched_hash( ) , CURRENT_BLOCK_NUMBER , true ) ]
2259+ #[ case:: block_hash_zero( proof_facts_with_zero_block_hash( ) , CURRENT_BLOCK_NUMBER , true ) ]
2260+ #[ case:: program_hash_invalid( proof_facts_with_invalid_program_hash( ) , CURRENT_BLOCK_NUMBER , true ) ]
2261+ fn test_validate_proof_facts (
2262+ default_all_resource_bounds : ValidResourceBounds ,
2263+ #[ case] proof_facts : ProofFacts ,
2264+ #[ case] current_block_number : u64 ,
2265+ #[ case] should_fail : bool ,
2266+ ) {
2267+ let mut block_context = BlockContext :: create_for_account_testing ( ) ;
2268+ block_context. block_info . block_number = BlockNumber ( current_block_number) ;
2269+
2270+ let chain_info = & block_context. chain_info ;
2271+ let account =
2272+ FeatureContract :: AccountWithoutValidations ( CairoVersion :: Cairo1 ( RunnableCairo1 :: Casm ) ) ;
2273+ let mut state = test_state ( chain_info, BALANCE , & [ ( account, 1u16 ) ] ) ;
2274+ let account_address = account. get_instance_address ( 0_u16 ) ;
2275+
2276+ let tx = invoke_tx_with_default_flags ( invoke_tx_args ! {
2277+ sender_address: account_address,
2278+ resource_bounds: default_all_resource_bounds,
2279+ proof_facts,
2280+ } ) ;
2281+
2282+ // Run only pre-validation stage (which includes proof facts validation).
2283+ let tx_context = block_context. to_tx_context ( & tx) ;
2284+ let result = tx. perform_pre_validation_stage ( & mut state, & tx_context) ;
2285+
2286+ if should_fail {
2287+ assert_matches ! ( result, Err ( TransactionPreValidationError :: InvalidProofFacts ( _) ) ) ;
2288+ } else {
2289+ assert_matches ! ( result, Ok ( ( ) ) ) ;
2290+ }
2291+ }
0 commit comments