Skip to content

Commit bfb567c

Browse files
committed
starknet_committer: compute and store accessed keys digest
1 parent 9885436 commit bfb567c

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/starknet_committer/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ license.workspace = true
77
description = "Computes and manages Starknet state."
88

99
[features]
10+
os_input = ["dep:blake2", "dep:digest"]
1011
testing = ["starknet_patricia/testing"]
1112

1213
[dependencies]
1314
apollo_config.workspace = true
1415
async-trait.workspace = true
16+
blake2 = { workspace = true, optional = true }
1517
derive_more = { workspace = true, features = ["as_ref", "from", "into"] }
18+
digest = { workspace = true, optional = true }
1619
ethnum.workspace = true
1720
pretty_assertions.workspace = true
1821
rand.workspace = true

crates/starknet_committer/src/db/serde_db_utils.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
#[cfg(feature = "os_input")]
2+
use blake2::Blake2s256;
3+
#[cfg(feature = "os_input")]
4+
use digest::Digest;
15
use serde::{Deserialize, Serialize};
26
use starknet_api::block::BlockNumber;
7+
#[cfg(feature = "os_input")]
8+
use starknet_patricia::patricia_merkle_tree::types::NodeIndex;
39
use starknet_patricia_storage::storage_trait::DbValue;
410
use starknet_types_core::felt::Felt;
511

12+
#[cfg(feature = "os_input")]
13+
use crate::patricia_merkle_tree::tree::SortedLeavesRequest;
14+
615
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Hash, Serialize)]
716
pub struct DbBlockNumber(pub BlockNumber);
817

@@ -23,3 +32,51 @@ pub fn serialize_felt_no_packing(felt: Felt) -> DbValue {
2332
pub fn deserialize_felt_no_packing(value: &DbValue) -> Felt {
2433
Felt::from_bytes_be_slice(&value.0)
2534
}
35+
36+
/// BLAKE2s-256 digest over a deterministic encoding of [`SortedLeavesRequest`].
37+
///
38+
/// The hashed payload is a concatenation length-prefixed big-endian 32-byte
39+
/// [`NodeIndex`] values (`idx.0.to_be_bytes()`), in this order:
40+
///
41+
/// 1. Classes trie — `len(classes_sorted)` then each class leaf index (already sorted).
42+
/// 2. Contracts trie — `len(contracts_sorted)` then each contract leaf index (already sorted).
43+
/// 3. Storage tries — `len(storage_sorted)` then, for each contract index in ascending order: the
44+
/// contract index, `len(storage slot indices)` for that contract, then each storage slot index
45+
/// (already sorted within the contract).
46+
#[cfg(feature = "os_input")]
47+
pub fn accessed_keys_digest(sorted: &SortedLeavesRequest<'_>) -> [u8; 32] {
48+
let mut payload = Vec::new();
49+
50+
let class = sorted.class_sorted.get_indices();
51+
payload.extend_from_slice(&encode_usize(class.len()));
52+
for idx in class {
53+
payload.extend_from_slice(&idx.0.to_be_bytes());
54+
}
55+
56+
let contract = sorted.contract_sorted.get_indices();
57+
payload.extend_from_slice(&encode_usize(contract.len()));
58+
for idx in contract {
59+
payload.extend_from_slice(&idx.0.to_be_bytes());
60+
}
61+
62+
let mut contract_indices: Vec<NodeIndex> = sorted.storage_sorted.keys().copied().collect();
63+
contract_indices.sort_unstable();
64+
65+
payload.extend_from_slice(&encode_usize(contract_indices.len()));
66+
for contract_idx in contract_indices {
67+
let sorted_slots = sorted.storage_sorted.get(&contract_idx).unwrap();
68+
payload.extend_from_slice(&contract_idx.0.to_be_bytes());
69+
let slot_indices = sorted_slots.get_indices();
70+
payload.extend_from_slice(&encode_usize(slot_indices.len()));
71+
for slot in slot_indices {
72+
payload.extend_from_slice(&slot.0.to_be_bytes());
73+
}
74+
}
75+
76+
Blake2s256::digest(&payload).into()
77+
}
78+
79+
#[cfg(feature = "os_input")]
80+
fn encode_usize(n: usize) -> [u8; 8] {
81+
u64::try_from(n).expect("accessed leaf count exceeds u64::MAX").to_be_bytes()
82+
}

0 commit comments

Comments
 (0)