Skip to content

Commit 95be2a2

Browse files
blockifier: test proof facts verifications
1 parent c6a2649 commit 95be2a2

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

crates/blockifier/src/transaction/account_transactions_test.rs

Lines changed: 85 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,82 @@ 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 (at the boundary).
2213+
fn too_recent_block_proof_facts() -> ProofFacts {
2214+
let mut snos_proof_facts =
2215+
SnosProofFacts::try_from(ProofFacts::snos_proof_facts_for_testing()).unwrap();
2216+
// Block number at the boundary: current - STORED_BLOCK_HASH_BUFFER, which is >= max_allowed.
2217+
snos_proof_facts.block_number = BlockNumber(CURRENT_BLOCK_NUMBER - STORED_BLOCK_HASH_BUFFER);
2218+
snos_to_proof_facts(snos_proof_facts)
2219+
}
2220+
2221+
/// Returns invalid proof_facts with a mismatched block hash.
2222+
fn mismatched_hash_proof_facts() -> ProofFacts {
2223+
let mut snos_proof_facts =
2224+
SnosProofFacts::try_from(ProofFacts::snos_proof_facts_for_testing()).unwrap();
2225+
//
2226+
snos_proof_facts.block_hash = BlockHash(snos_proof_facts.block_hash.0 + 1);
2227+
snos_to_proof_facts(snos_proof_facts)
2228+
}
2229+
2230+
/// Returns invalid proof_facts with a zero block hash.
2231+
fn zero_block_hash_proof_facts() -> ProofFacts {
2232+
let mut snos_proof_facts = SnosProofFacts::try_from(ProofFacts::snos_proof_facts_for_testing())
2233+
.expect("Invalid proof facts");
2234+
snos_proof_facts.block_hash = BlockHash(Felt::ZERO);
2235+
snos_to_proof_facts(snos_proof_facts)
2236+
}
2237+
2238+
/// Tests the `validate_proof_facts` function for Invoke V3 transactions.
2239+
/// Covers: valid proof facts, too recent block number, mismatched block hash, future block,
2240+
/// current block too small, and zero block hash.
2241+
#[rstest]
2242+
#[case::valid_proof_facts(ProofFacts::snos_proof_facts_for_testing(), CURRENT_BLOCK_NUMBER)]
2243+
#[should_panic(expected = "is too recent. The maximum allowed")]
2244+
#[case::too_recent_block(too_recent_block_proof_facts(), CURRENT_BLOCK_NUMBER)]
2245+
#[should_panic(expected = "Block hash mismatch")]
2246+
#[case::mismatched_block_hash(mismatched_hash_proof_facts(), CURRENT_BLOCK_NUMBER)]
2247+
#[should_panic(expected = "is too recent to have a stored block hash")]
2248+
#[case::current_block_too_small(
2249+
ProofFacts::snos_proof_facts_for_testing(),
2250+
STORED_BLOCK_HASH_BUFFER - 1,
2251+
)]
2252+
#[should_panic(expected = "Stored block hash is zero")]
2253+
#[case::zero_block_hash(zero_block_hash_proof_facts(), CURRENT_BLOCK_NUMBER)]
2254+
fn test_validate_proof_facts(
2255+
default_all_resource_bounds: ValidResourceBounds,
2256+
#[case] proof_facts: ProofFacts,
2257+
#[case] current_block_number: u64,
2258+
) {
2259+
let mut block_context = BlockContext::create_for_account_testing();
2260+
block_context.block_info.block_number = BlockNumber(current_block_number);
2261+
2262+
let chain_info = &block_context.chain_info;
2263+
let account =
2264+
FeatureContract::AccountWithoutValidations(CairoVersion::Cairo1(RunnableCairo1::Casm));
2265+
let mut state = test_state(chain_info, BALANCE, &[(account, 1u16)]);
2266+
let account_address = account.get_instance_address(0_u16);
2267+
2268+
let tx = invoke_tx_with_default_flags(invoke_tx_args! {
2269+
sender_address: account_address,
2270+
resource_bounds: default_all_resource_bounds,
2271+
proof_facts,
2272+
});
2273+
2274+
// Run only pre-validation stage (which includes proof facts validation).
2275+
let tx_context = block_context.to_tx_context(&tx);
2276+
tx.perform_pre_validation_stage(&mut state, &tx_context).unwrap();
2277+
}

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)