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