Skip to content

Commit 9b31a07

Browse files
avi-starkwareclaude
andcommitted
starknet_transaction_prover: add committer utils unit tests
Add 8 unit tests for state-diff validation and conversion utilities: empty/valid/invalid state diffs, class-hash-only updates, nonce-only updates, storage-only updates, zero-value filtering, and multi-contract mixed updates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b174fa7 commit 9b31a07

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

crates/starknet_transaction_prover/src/running.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub mod virtual_block_executor;
1616
#[cfg(test)]
1717
mod classes_provider_test;
1818
#[cfg(test)]
19+
mod committer_utils_test;
20+
#[cfg(test)]
1921
pub mod rpc_records;
2022
#[cfg(test)]
2123
mod rpc_records_test;
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
use std::collections::HashMap;
2+
3+
use assert_matches::assert_matches;
4+
use blockifier::state::cached_state::StateMaps;
5+
use rstest::rstest;
6+
use starknet_api::core::{ClassHash, ContractAddress, Nonce};
7+
use starknet_api::state::StorageKey;
8+
use starknet_committer::block_committer::input::{
9+
StarknetStorageKey,
10+
StarknetStorageValue,
11+
StateDiff,
12+
};
13+
use starknet_committer::patricia_merkle_tree::types::CompiledClassHash as CommitterCompiledClassHash;
14+
use starknet_types_core::felt::Felt;
15+
16+
use crate::errors::ProofProviderError;
17+
use crate::running::committer_utils::{
18+
state_maps_to_committer_state_diff,
19+
validate_virtual_os_state_diff,
20+
};
21+
22+
fn make_contract_address(value: u64) -> ContractAddress {
23+
ContractAddress::try_from(Felt::from(value)).unwrap()
24+
}
25+
26+
// validate_virtual_os_state_diff tests
27+
28+
#[test]
29+
fn test_validate_empty_state_diff() {
30+
let state_diff = StateDiff {
31+
address_to_class_hash: Default::default(),
32+
address_to_nonce: Default::default(),
33+
class_hash_to_compiled_class_hash: Default::default(),
34+
storage_updates: Default::default(),
35+
};
36+
assert!(validate_virtual_os_state_diff(&state_diff).is_ok());
37+
}
38+
39+
#[test]
40+
fn test_validate_state_diff_with_valid_storage_updates() {
41+
let address = make_contract_address(1);
42+
let storage_key = StarknetStorageKey(StorageKey::from(1u32));
43+
let non_zero_value = StarknetStorageValue(Felt::from(42u64));
44+
45+
let mut address_storage: HashMap<StarknetStorageKey, StarknetStorageValue> = HashMap::new();
46+
address_storage.insert(storage_key, non_zero_value);
47+
48+
let mut storage_updates: HashMap<
49+
ContractAddress,
50+
HashMap<StarknetStorageKey, StarknetStorageValue>,
51+
> = HashMap::new();
52+
storage_updates.insert(address, address_storage);
53+
54+
let state_diff = StateDiff {
55+
address_to_class_hash: Default::default(),
56+
address_to_nonce: Default::default(),
57+
class_hash_to_compiled_class_hash: Default::default(),
58+
storage_updates,
59+
};
60+
assert!(validate_virtual_os_state_diff(&state_diff).is_ok());
61+
}
62+
63+
#[test]
64+
fn test_validate_state_diff_with_valid_nonce_updates() {
65+
let address = make_contract_address(1);
66+
let storage_key = StarknetStorageKey(StorageKey::from(1u32));
67+
let non_zero_value = StarknetStorageValue(Felt::from(42u64));
68+
69+
let mut address_storage: HashMap<StarknetStorageKey, StarknetStorageValue> = HashMap::new();
70+
address_storage.insert(storage_key, non_zero_value);
71+
72+
let mut storage_updates: HashMap<
73+
ContractAddress,
74+
HashMap<StarknetStorageKey, StarknetStorageValue>,
75+
> = HashMap::new();
76+
storage_updates.insert(address, address_storage);
77+
78+
let mut address_to_nonce = HashMap::new();
79+
address_to_nonce.insert(address, Nonce(Felt::from(1u64)));
80+
81+
let state_diff = StateDiff {
82+
address_to_class_hash: Default::default(),
83+
address_to_nonce,
84+
class_hash_to_compiled_class_hash: Default::default(),
85+
storage_updates,
86+
};
87+
assert!(validate_virtual_os_state_diff(&state_diff).is_ok());
88+
}
89+
90+
#[rstest]
91+
#[case("Storage deletion", {
92+
let address = make_contract_address(1);
93+
let storage_key = StarknetStorageKey(StorageKey::from(1u32));
94+
let zero_value = StarknetStorageValue(Felt::ZERO);
95+
let mut address_storage: HashMap<StarknetStorageKey, StarknetStorageValue> = HashMap::new();
96+
address_storage.insert(storage_key, zero_value);
97+
let mut storage_updates: HashMap<ContractAddress, HashMap<StarknetStorageKey, StarknetStorageValue>> =
98+
HashMap::new();
99+
storage_updates.insert(address, address_storage);
100+
StateDiff {
101+
address_to_class_hash: Default::default(),
102+
address_to_nonce: Default::default(),
103+
class_hash_to_compiled_class_hash: Default::default(),
104+
storage_updates,
105+
}
106+
})]
107+
#[case("Contract deployments", {
108+
let address = make_contract_address(1);
109+
let class_hash = ClassHash(Felt::from(0x42u64));
110+
let mut address_to_class_hash = HashMap::new();
111+
address_to_class_hash.insert(address, class_hash);
112+
StateDiff {
113+
address_to_class_hash,
114+
address_to_nonce: Default::default(),
115+
class_hash_to_compiled_class_hash: Default::default(),
116+
storage_updates: Default::default(),
117+
}
118+
})]
119+
#[case("Contract declarations", {
120+
let class_hash = ClassHash(Felt::from(0x42u64));
121+
let compiled_class_hash = CommitterCompiledClassHash(Felt::from(0x99u64));
122+
let mut class_hash_to_compiled_class_hash = HashMap::new();
123+
class_hash_to_compiled_class_hash.insert(class_hash, compiled_class_hash);
124+
StateDiff {
125+
address_to_class_hash: Default::default(),
126+
address_to_nonce: Default::default(),
127+
class_hash_to_compiled_class_hash,
128+
storage_updates: Default::default(),
129+
}
130+
})]
131+
fn test_validate_rejects_invalid_state_diff(
132+
#[case] expected_error_substring: &str,
133+
#[case] state_diff: StateDiff,
134+
) {
135+
let error = validate_virtual_os_state_diff(&state_diff).unwrap_err();
136+
assert_matches!(
137+
&error,
138+
ProofProviderError::InvalidStateDiff(message) if message.contains(expected_error_substring)
139+
);
140+
}
141+
142+
// state_maps_to_committer_state_diff tests
143+
144+
#[test]
145+
fn test_convert_empty_state_maps() {
146+
let state_maps = StateMaps::default();
147+
let state_diff = state_maps_to_committer_state_diff(state_maps);
148+
149+
assert!(state_diff.address_to_class_hash.is_empty());
150+
assert!(state_diff.address_to_nonce.is_empty());
151+
assert!(state_diff.class_hash_to_compiled_class_hash.is_empty());
152+
assert!(state_diff.storage_updates.is_empty());
153+
}
154+
155+
#[test]
156+
fn test_convert_state_maps_preserves_nonces() {
157+
let address = make_contract_address(1);
158+
let nonce = Nonce(Felt::from(7u64));
159+
160+
let mut state_maps = StateMaps::default();
161+
state_maps.nonces.insert(address, nonce);
162+
163+
let state_diff = state_maps_to_committer_state_diff(state_maps);
164+
165+
assert_eq!(state_diff.address_to_nonce.get(&address), Some(&nonce));
166+
assert_eq!(state_diff.address_to_nonce.len(), 1);
167+
}
168+
169+
#[test]
170+
fn test_convert_state_maps_preserves_storage() {
171+
let address = make_contract_address(1);
172+
let storage_key = StorageKey::from(5u32);
173+
let storage_value = Felt::from(100u64);
174+
175+
let mut state_maps = StateMaps::default();
176+
state_maps.storage.insert((address, storage_key), storage_value);
177+
178+
let state_diff = state_maps_to_committer_state_diff(state_maps);
179+
180+
let committer_key = StarknetStorageKey(storage_key);
181+
let committer_value = StarknetStorageValue(storage_value);
182+
183+
let address_storage =
184+
state_diff.storage_updates.get(&address).expect("Address should be in storage_updates");
185+
assert_eq!(address_storage.get(&committer_key), Some(&committer_value));
186+
}
187+
188+
#[test]
189+
fn test_convert_state_maps_preserves_compiled_class_hashes() {
190+
let class_hash = ClassHash(Felt::from(0x42u64));
191+
let compiled_class_hash = starknet_api::core::CompiledClassHash(Felt::from(0x99u64));
192+
193+
let mut state_maps = StateMaps::default();
194+
state_maps.compiled_class_hashes.insert(class_hash, compiled_class_hash);
195+
196+
let state_diff = state_maps_to_committer_state_diff(state_maps);
197+
198+
let expected_committer_hash = CommitterCompiledClassHash(compiled_class_hash.0);
199+
assert_eq!(
200+
state_diff.class_hash_to_compiled_class_hash.get(&class_hash),
201+
Some(&expected_committer_hash)
202+
);
203+
assert_eq!(state_diff.class_hash_to_compiled_class_hash.len(), 1);
204+
}

0 commit comments

Comments
 (0)