Skip to content

Commit d2cc76f

Browse files
committed
starknet_committer: add commit e2e tests
1 parent 437648a commit d2cc76f

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

crates/starknet_committer/src/block_committer.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
pub mod commit;
2+
#[cfg(test)]
3+
pub mod commit_test;
24
pub mod errors;
35
pub mod input;
46
#[cfg(any(feature = "testing", test))]
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
use std::collections::HashMap;
2+
use std::sync::LazyLock;
3+
4+
use rand::rngs::SmallRng;
5+
use rand::SeedableRng;
6+
use rstest::rstest;
7+
use rstest_reuse::{apply, template};
8+
use starknet_api::core::{ClassHash, ContractAddress};
9+
use starknet_api::hash::{HashOutput, StateRoots};
10+
use starknet_patricia_storage::map_storage::MapStorage;
11+
use starknet_types_core::felt::Felt;
12+
13+
use crate::block_committer::commit::commit_block;
14+
use crate::block_committer::input::{
15+
Input,
16+
InputContext,
17+
ReaderConfig,
18+
StarknetStorageKey,
19+
StarknetStorageValue,
20+
StateDiff,
21+
};
22+
use crate::block_committer::state_diff_generator::generate_random_state_diff;
23+
use crate::db::facts_db::db::FactsDb;
24+
use crate::db::facts_db::types::FactsDbInitialRead;
25+
use crate::db::forest_trait::{ForestReader, ForestWriter};
26+
use crate::db::index_db::db::IndexDb;
27+
use crate::patricia_merkle_tree::types::CompiledClassHash;
28+
29+
static FIRST_CONTRACT_ADDRESS: LazyLock<ContractAddress> =
30+
LazyLock::new(|| ContractAddress::from(1_u128));
31+
static SECOND_CONTRACT_ADDRESS: LazyLock<ContractAddress> =
32+
LazyLock::new(|| ContractAddress::from(1_u128 << 100));
33+
34+
const EXPECTED_ROOTS_SIMPLE_CASE: StateRoots = StateRoots {
35+
contracts_trie_root_hash: HashOutput(Felt::from_hex_unchecked(
36+
"0x1dfab71737a9b4528835c11c3cef25d2587ef8afe5098d3b21f2ea77e944500",
37+
)),
38+
classes_trie_root_hash: HashOutput(Felt::from_hex_unchecked(
39+
"0x7ae8007b033a1c032c6a791331f56a652833b0b25633587318276f4462c8c1c",
40+
)),
41+
};
42+
43+
const EXPECTED_ROOTS_RANDOM_CASE: StateRoots = StateRoots {
44+
contracts_trie_root_hash: HashOutput(Felt::from_hex_unchecked(
45+
"0x2877d3a2370c501255c8451f615f4f2aa900f6acf2f0cd36b735b1108a4a0e4",
46+
)),
47+
classes_trie_root_hash: HashOutput(Felt::from_hex_unchecked("0x0")),
48+
};
49+
50+
const N_RANDOM_STATE_UPDATES: usize = 200;
51+
52+
#[template]
53+
#[rstest]
54+
#[case([get_first_state_diff(), get_second_state_diff()], EXPECTED_ROOTS_SIMPLE_CASE)]
55+
#[case(get_random_state_diffs(), EXPECTED_ROOTS_RANDOM_CASE)]
56+
fn state_diff_cases(#[case] state_diffs: [StateDiff; 2], #[case] expected_roots: StateRoots) {}
57+
58+
#[apply(state_diff_cases)]
59+
#[tokio::test]
60+
#[rstest]
61+
async fn test_commit_two_consequtive_blocks_facts_layout(
62+
#[case] state_diffs: [StateDiff; 2],
63+
#[case] expected_roots: StateRoots,
64+
) {
65+
test_commit_two_consequtive_blocks::<FactsDbInitialRead, FactsDb<MapStorage>>(
66+
|storage| FactsDb::new(storage),
67+
FactsDbInitialRead::default(),
68+
state_diffs,
69+
expected_roots,
70+
)
71+
.await;
72+
}
73+
74+
#[apply(state_diff_cases)]
75+
#[tokio::test]
76+
#[rstest]
77+
async fn test_commit_two_consequtive_blocks_index_layout(
78+
#[case] state_diffs: [StateDiff; 2],
79+
#[case] expected_roots: StateRoots,
80+
) {
81+
test_commit_two_consequtive_blocks::<FactsDbInitialRead, IndexDb<MapStorage>>(
82+
|storage| IndexDb::new(storage),
83+
FactsDbInitialRead::default(),
84+
state_diffs,
85+
expected_roots,
86+
)
87+
.await;
88+
}
89+
90+
async fn test_commit_two_consequtive_blocks<
91+
ReaderInputContext: InputContext + Clone,
92+
Db: ForestReader<ReaderInputContext> + ForestWriter,
93+
>(
94+
db_generator: impl FnOnce(MapStorage) -> Db,
95+
initial_read_context: ReaderInputContext,
96+
state_diffs: [StateDiff; 2],
97+
expected_roots: StateRoots,
98+
) {
99+
let [first_state_diff, second_state_diff] = state_diffs;
100+
101+
let storage = MapStorage::default();
102+
let mut db = db_generator(storage);
103+
104+
let mut input = Input {
105+
state_diff: first_state_diff,
106+
initial_read_context: initial_read_context.clone(),
107+
config: ReaderConfig::default(),
108+
};
109+
let filled_forest = commit_block(input, &mut db, None).await.unwrap();
110+
db.write(&filled_forest).await.unwrap();
111+
112+
input = Input {
113+
state_diff: second_state_diff,
114+
initial_read_context,
115+
config: ReaderConfig::default(),
116+
};
117+
118+
let filled_forest = commit_block(input, &mut db, None).await.unwrap();
119+
db.write(&filled_forest).await.unwrap();
120+
121+
assert_eq!(filled_forest.state_roots(), expected_roots);
122+
}
123+
124+
fn get_first_state_diff() -> StateDiff {
125+
let mut contract_class_changes = HashMap::new();
126+
contract_class_changes.insert(*FIRST_CONTRACT_ADDRESS, ClassHash(Felt::ONE));
127+
contract_class_changes.insert(*SECOND_CONTRACT_ADDRESS, ClassHash(Felt::TWO));
128+
129+
let mut individual_storage_changes = HashMap::new();
130+
individual_storage_changes
131+
.insert(StarknetStorageKey::from(1_u128), StarknetStorageValue(Felt::from(1_u128)));
132+
individual_storage_changes
133+
.insert(StarknetStorageKey::from(2_u128), StarknetStorageValue(Felt::from(2_u128)));
134+
135+
let mut storage_updates = HashMap::new();
136+
storage_updates.insert(*FIRST_CONTRACT_ADDRESS, individual_storage_changes.clone());
137+
storage_updates.insert(*SECOND_CONTRACT_ADDRESS, individual_storage_changes);
138+
139+
StateDiff {
140+
address_to_class_hash: contract_class_changes,
141+
address_to_nonce: HashMap::new(),
142+
class_hash_to_compiled_class_hash: HashMap::new(),
143+
storage_updates,
144+
}
145+
}
146+
147+
fn get_second_state_diff() -> StateDiff {
148+
let mut contract_class_changes = HashMap::new();
149+
contract_class_changes.insert(*FIRST_CONTRACT_ADDRESS, ClassHash(Felt::TWO));
150+
151+
let mut individual_storage_changes = HashMap::new();
152+
individual_storage_changes
153+
.insert(StarknetStorageKey::from(1_u128), StarknetStorageValue(Felt::from(2_u128)));
154+
individual_storage_changes
155+
.insert(StarknetStorageKey::from(2_u128), StarknetStorageValue(Felt::from(4_u128)));
156+
157+
let mut storage_updates = HashMap::new();
158+
storage_updates.insert(*SECOND_CONTRACT_ADDRESS, individual_storage_changes);
159+
160+
let mut declerations = HashMap::new();
161+
declerations.insert(ClassHash(Felt::THREE), CompiledClassHash(Felt::THREE));
162+
163+
StateDiff {
164+
address_to_class_hash: contract_class_changes,
165+
address_to_nonce: HashMap::new(),
166+
class_hash_to_compiled_class_hash: declerations,
167+
storage_updates,
168+
}
169+
}
170+
171+
fn get_random_state_diffs() -> [StateDiff; 2] {
172+
// Use a constant seed for reproducibility.
173+
let mut seed = 42_u64;
174+
let mut rng = SmallRng::seed_from_u64(seed);
175+
let first_state_diff = generate_random_state_diff(&mut rng, N_RANDOM_STATE_UPDATES, None);
176+
seed += 1;
177+
rng = SmallRng::seed_from_u64(seed);
178+
let second_state_diff = generate_random_state_diff(&mut rng, N_RANDOM_STATE_UPDATES, None);
179+
[first_state_diff, second_state_diff]
180+
}

crates/starknet_committer/src/db/facts_db/types.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,16 @@ impl<'a> SubTreeTrait<'a> for FactsSubTree<'a> {
6262
}
6363
}
6464
/// Used for reading the roots in facts layout case.
65-
#[derive(Debug, PartialEq)]
65+
#[derive(Clone, Debug, PartialEq)]
6666
pub struct FactsDbInitialRead(pub StateRoots);
6767

68+
impl Default for FactsDbInitialRead {
69+
fn default() -> Self {
70+
Self(StateRoots {
71+
contracts_trie_root_hash: HashOutput::ROOT_OF_EMPTY_TREE,
72+
classes_trie_root_hash: HashOutput::ROOT_OF_EMPTY_TREE,
73+
})
74+
}
75+
}
76+
6877
impl InputContext for FactsDbInitialRead {}

0 commit comments

Comments
 (0)