Skip to content

Commit 5bbd2c9

Browse files
blockifier: test proof facts verifications
1 parent feee81f commit 5bbd2c9

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

crates/blockifier/src/transaction/account_transactions_test.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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};
2121
use starknet_api::contract_class::compiled_class_hash::{HashVersion, HashableCompiledClass};
2222
use starknet_api::contract_class::ContractClass;
2323
use starknet_api::core::{
@@ -41,6 +41,7 @@ use starknet_api::test_utils::deploy_account::executable_deploy_account_tx;
4141
use starknet_api::test_utils::invoke::{executable_invoke_tx, InvokeTxArgs};
4242
use 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
};
6266
use starknet_api::transaction::{
6367
DeclareTransaction,
@@ -79,6 +83,7 @@ use starknet_api::{
7983
};
8084
use starknet_types_core::felt::Felt;
8185

86+
use crate::abi::constants::STORED_BLOCK_HASH_BUFFER;
8287
use crate::context::{BlockContext, TransactionContext};
8388
use crate::execution::call_info::CallInfo;
8489
use 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+
}

crates/starknet_api/src/transaction/fields.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,18 @@ impl From<Vec<Felt>> for ProofFacts {
701701
}
702702
}
703703

704+
impl TryFrom<ProofFacts> for SnosProofFacts {
705+
type Error = StarknetApiError;
706+
fn try_from(proof_facts: ProofFacts) -> Result<Self, Self::Error> {
707+
match ProofFactsVariant::try_from(&proof_facts) {
708+
Ok(ProofFactsVariant::Snos(snos_proof_facts)) => Ok(snos_proof_facts),
709+
_ => Err(StarknetApiError::InvalidProofFacts(format!(
710+
"Invalid SNOS proof facts: {proof_facts:?}",
711+
))),
712+
}
713+
}
714+
}
715+
704716
/// Client-provided proof used for client-side proving.
705717
#[derive(
706718
Clone,

0 commit comments

Comments
 (0)