@@ -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,100 @@ 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.
2213+ fn too_recent_block_proof_facts ( ) -> ProofFacts {
2214+ let mut snos_proof_facts = SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) )
2215+ . expect ( "Invalid proof facts" ) ;
2216+ snos_proof_facts. block_number = BlockNumber ( CURRENT_BLOCK_NUMBER - STORED_BLOCK_HASH_BUFFER ) ;
2217+ snos_to_proof_facts ( snos_proof_facts)
2218+ }
2219+
2220+ /// Returns invalid proof_facts with a mismatched block hash.
2221+ fn mismatched_hash_proof_facts ( ) -> ProofFacts {
2222+ let mut snos_proof_facts = SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) )
2223+ . expect ( "Invalid proof facts" ) ;
2224+ snos_proof_facts. block_hash = BlockHash ( felt ! ( 0xDEADBEEF_u64 ) ) ;
2225+ snos_to_proof_facts ( snos_proof_facts)
2226+ }
2227+
2228+ /// Returns invalid proof_facts with a block number greater than the current block number.
2229+ fn future_block_proof_facts ( ) -> ProofFacts {
2230+ let mut snos_proof_facts = SnosProofFacts :: try_from ( ProofFacts :: snos_proof_facts_for_testing ( ) )
2231+ . expect ( "Invalid proof facts" ) ;
2232+ snos_proof_facts. block_number = BlockNumber ( CURRENT_BLOCK_NUMBER + 100 ) ;
2233+ snos_to_proof_facts ( snos_proof_facts)
2234+ }
2235+
2236+ /// Tests the `validate_proof_facts` function for Invoke V3 transactions.
2237+ /// Covers: valid proof facts, too recent block number, mismatched block hash, and future block.
2238+ #[ rstest]
2239+ #[ case:: valid_proof_facts( ProofFacts :: snos_proof_facts_for_testing( ) , CURRENT_BLOCK_NUMBER ) ]
2240+ #[ should_panic( expected = "is too recent" ) ]
2241+ #[ case:: too_recent_block( too_recent_block_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2242+ #[ should_panic( expected = "Block hash mismatch" ) ]
2243+ #[ case:: mismatched_block_hash( mismatched_hash_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2244+ #[ should_panic( expected = "is less than proof block number" ) ]
2245+ #[ case:: future_block( future_block_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2246+ fn test_validate_proof_facts (
2247+ default_all_resource_bounds : ValidResourceBounds ,
2248+ #[ case] proof_facts : ProofFacts ,
2249+ #[ case] current_block_number : u64 ,
2250+ ) {
2251+ let mut block_context = BlockContext :: create_for_account_testing ( ) ;
2252+ block_context. block_info . block_number = BlockNumber ( current_block_number) ;
2253+
2254+ let chain_info = & block_context. chain_info ;
2255+ let account = FeatureContract :: AccountWithoutValidations ( CairoVersion :: Cairo0 ) ;
2256+ let mut state = test_state ( chain_info, BALANCE , & [ ( account, 1u16 ) ] ) ;
2257+ let account_address = account. get_instance_address ( 0_u16 ) ;
2258+
2259+ // Get the block hash contract address from versioned constants.
2260+ let block_hash_contract_address = block_context
2261+ . versioned_constants
2262+ . os_constants
2263+ . os_contract_addresses
2264+ . block_hash_contract_address ( ) ;
2265+
2266+ // Store block hashes for test blocks.
2267+ // Valid block number: more than STORED_BLOCK_HASH_BUFFER blocks old.
2268+ let valid_proof_block_number = CURRENT_BLOCK_NUMBER - STORED_BLOCK_HASH_BUFFER - 1 ;
2269+ let stored_block_hash = felt ! (
2270+ SnosProofFacts :: try_from( ProofFacts :: snos_proof_facts_for_testing( ) )
2271+ . expect( "Invalid proof facts" )
2272+ . block_hash
2273+ . 0
2274+ ) ;
2275+
2276+ // Store the block hash in the block hash contract.
2277+ state
2278+ . set_storage_at (
2279+ block_hash_contract_address,
2280+ StorageKey :: try_from ( felt ! ( valid_proof_block_number) ) . unwrap ( ) ,
2281+ stored_block_hash,
2282+ )
2283+ . unwrap ( ) ;
2284+
2285+ let tx = invoke_tx_with_default_flags ( invoke_tx_args ! {
2286+ sender_address: account_address,
2287+ resource_bounds: default_all_resource_bounds,
2288+ version: TransactionVersion :: THREE ,
2289+ proof_facts: proof_facts,
2290+ } ) ;
2291+
2292+ // Run only pre-validation stage (which includes proof facts validation).
2293+ let tx_context = block_context. to_tx_context ( & tx) ;
2294+ tx. perform_pre_validation_stage ( & mut state, & tx_context) . unwrap ( ) ;
2295+ }
0 commit comments