@@ -8,6 +8,7 @@ use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, Nonce};
88use starknet_api:: data_availability:: DataAvailabilityMode ;
99use starknet_api:: executable_transaction:: { AccountTransaction as Transaction , TransactionType } ;
1010use starknet_api:: execution_resources:: GasAmount ;
11+ use starknet_api:: state:: StorageKey ;
1112use starknet_api:: transaction:: fields:: Resource :: { L1DataGas , L1Gas , L2Gas } ;
1213use starknet_api:: transaction:: fields:: {
1314 AccountDeploymentData ,
@@ -24,6 +25,7 @@ use starknet_api::transaction::{constants, TransactionHash, TransactionVersion};
2425use starknet_types_core:: felt:: Felt ;
2526
2627use super :: errors:: ResourceBoundsError ;
28+ use crate :: abi:: constants:: STORED_BLOCK_HASH_BUFFER ;
2729use crate :: context:: { BlockContext , GasCounter , TransactionContext } ;
2830use crate :: execution:: call_info:: CallInfo ;
2931use crate :: execution:: common_hints:: ExecutionMode ;
@@ -246,15 +248,49 @@ impl AccountTransaction {
246248 }
247249 }
248250
249- fn validate_proof_facts ( & self ) -> TransactionPreValidationResult < ( ) > {
251+ fn validate_proof_facts (
252+ & self ,
253+ tx_context : & TransactionContext ,
254+ state : & mut dyn State ,
255+ ) -> TransactionPreValidationResult < ( ) > {
250256 if let Transaction :: Invoke ( tx) = & self . tx {
251257 if tx. tx . version ( ) == TransactionVersion :: THREE {
252258 let proof_facts_variant = ProofFactsVariant :: try_from ( & tx. tx . proof_facts ( ) )
253259 . map_err ( |e| TransactionPreValidationError :: InvalidProofFacts ( e. to_string ( ) ) ) ?;
254260 match proof_facts_variant {
255261 ProofFactsVariant :: Empty => { }
256- ProofFactsVariant :: Snos ( _snos_proof_facts) => {
257- // TODO(Meshi/ AvivG): add proof facts validations.
262+ ProofFactsVariant :: Snos ( snos_proof_facts) => {
263+ // TODO(Meshi/AvivG): Add more proof facts validations.
264+ let proof_block_number = snos_proof_facts. block_number ;
265+ let proof_block_hash = snos_proof_facts. block_hash . 0 ;
266+
267+ // Validate block number is not too recent.
268+ let current_block_number = tx_context. block_context . block_info . block_number ;
269+ if current_block_number. 0 - proof_block_number. 0 < STORED_BLOCK_HASH_BUFFER
270+ {
271+ return Err ( TransactionPreValidationError :: InvalidProofFacts ( format ! (
272+ "Proof block number is too recent. Proof block number: \
273+ {proof_block_number}, current block number: \
274+ {current_block_number}."
275+ ) ) ) ;
276+ }
277+
278+ // Validate that the proof block hash matches the stored hash.
279+ let os_addresses = & tx_context
280+ . block_context
281+ . versioned_constants
282+ . os_constants
283+ . os_contract_addresses ;
284+ let stored_block_hash = state. get_storage_at (
285+ os_addresses. block_hash_contract_address ( ) ,
286+ StorageKey :: from ( proof_block_number. 0 ) ,
287+ ) ?;
288+ if stored_block_hash != proof_block_hash {
289+ return Err ( TransactionPreValidationError :: InvalidProofFacts ( format ! (
290+ "Block hash mismatch for block {proof_block_number}. Proof block \
291+ hash: {proof_block_hash}, stored block hash: {stored_block_hash}."
292+ ) ) ) ;
293+ }
258294 }
259295 }
260296 }
@@ -278,7 +314,7 @@ impl AccountTransaction {
278314 verify_can_pay_committed_bounds ( state, tx_context) . map_err ( Box :: new) ?;
279315 }
280316
281- self . validate_proof_facts ( ) ?;
317+ self . validate_proof_facts ( tx_context , state ) ?;
282318
283319 Ok ( ( ) )
284320 }
0 commit comments