@@ -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,119 @@ 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+ /// Returns invalid proof_facts with block number 0 (for testing low current block number).
2253+ fn block_zero_proof_facts ( ) -> ProofFacts {
2254+ snos_to_proof_facts ( SnosProofFacts { block_number : BlockNumber ( 0 ) , ..valid_snos_proof_facts ( ) } )
2255+ }
2256+
2257+ /// Tests the `validate_proof_facts` function for Invoke V3 transactions.
2258+ /// Covers: valid proof facts, too recent block number, mismatched block hash, future block,
2259+ /// and low current block number.
2260+ #[ rstest]
2261+ #[ case:: valid_proof_facts( valid_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2262+ #[ should_panic( expected = "is too recent" ) ]
2263+ #[ case:: too_recent_block( too_recent_block_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2264+ #[ should_panic( expected = "Block hash mismatch" ) ]
2265+ #[ case:: mismatched_block_hash( mismatched_hash_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2266+ #[ should_panic( expected = "is less than proof block number" ) ]
2267+ #[ case:: future_block( future_block_proof_facts( ) , CURRENT_BLOCK_NUMBER ) ]
2268+ #[ should_panic( expected = "is less than STORED_BLOCK_HASH_BUFFER" ) ]
2269+ #[ case:: low_current_block_number( block_zero_proof_facts( ) , STORED_BLOCK_HASH_BUFFER ) ]
2270+ fn test_validate_proof_facts (
2271+ default_all_resource_bounds : ValidResourceBounds ,
2272+ #[ case] proof_facts : ProofFacts ,
2273+ #[ case] current_block_number : u64 ,
2274+ ) {
2275+ let mut block_context = BlockContext :: create_for_account_testing ( ) ;
2276+ block_context. block_info . block_number = BlockNumber ( current_block_number) ;
2277+
2278+ let chain_info = & block_context. chain_info ;
2279+ let account = FeatureContract :: AccountWithoutValidations ( CairoVersion :: Cairo0 ) ;
2280+ let mut state = test_state ( chain_info, BALANCE , & [ ( account, 1u16 ) ] ) ;
2281+ let account_address = account. get_instance_address ( 0_u16 ) ;
2282+
2283+ // Get the block hash contract address from versioned constants.
2284+ let block_hash_contract_address = block_context
2285+ . versioned_constants
2286+ . os_constants
2287+ . os_contract_addresses
2288+ . block_hash_contract_address ( ) ;
2289+
2290+ // Store block hashes for test blocks.
2291+ // Valid block number: more than STORED_BLOCK_HASH_BUFFER blocks old.
2292+ let valid_proof_block_number = CURRENT_BLOCK_NUMBER - STORED_BLOCK_HASH_BUFFER - 1 ;
2293+ let stored_block_hash = felt ! ( 0xABCDEF_u64 ) ;
2294+
2295+ // Store the block hash in the block hash contract.
2296+ state
2297+ . set_storage_at (
2298+ block_hash_contract_address,
2299+ StorageKey :: try_from ( felt ! ( valid_proof_block_number) ) . unwrap ( ) ,
2300+ stored_block_hash,
2301+ )
2302+ . unwrap ( ) ;
2303+
2304+ let tx = invoke_tx_with_default_flags ( invoke_tx_args ! {
2305+ sender_address: account_address,
2306+ resource_bounds: default_all_resource_bounds,
2307+ version: TransactionVersion :: THREE ,
2308+ proof_facts: proof_facts,
2309+ } ) ;
2310+
2311+ // Run only pre-validation stage (which includes proof facts validation).
2312+ let tx_context = block_context. to_tx_context ( & tx) ;
2313+ tx. perform_pre_validation_stage ( & mut state, & tx_context) . unwrap ( ) ;
2314+ }
0 commit comments