Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/starknet_committer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ license.workspace = true
description = "Computes and manages Starknet state."

[features]
os_input = ["dep:blake2", "dep:digest"]
testing = ["starknet_patricia/testing"]

[dependencies]
apollo_config.workspace = true
async-trait.workspace = true
blake2 = { workspace = true, optional = true }
derive_more = { workspace = true, features = ["as_ref", "from", "into"] }
digest = { workspace = true, optional = true }
ethnum.workspace = true
pretty_assertions.workspace = true
rand.workspace = true
Expand Down
57 changes: 57 additions & 0 deletions crates/starknet_committer/src/db/serde_db_utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
#[cfg(feature = "os_input")]
use blake2::Blake2s256;
#[cfg(feature = "os_input")]
use digest::Digest;
use serde::{Deserialize, Serialize};
use starknet_api::block::BlockNumber;
#[cfg(feature = "os_input")]
use starknet_patricia::patricia_merkle_tree::types::NodeIndex;
use starknet_patricia_storage::storage_trait::DbValue;
use starknet_types_core::felt::Felt;

#[cfg(feature = "os_input")]
use crate::patricia_merkle_tree::tree::SortedLeavesRequest;

#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Hash, Serialize)]
pub struct DbBlockNumber(pub BlockNumber);

Expand All @@ -23,3 +32,51 @@ pub fn serialize_felt_no_packing(felt: Felt) -> DbValue {
pub fn deserialize_felt_no_packing(value: &DbValue) -> Felt {
Felt::from_bytes_be_slice(&value.0)
}

/// BLAKE2s-256 digest over a deterministic encoding of [`SortedLeavesRequest`].
///
/// The hashed payload is a concatenation length-prefixed big-endian 32-byte
/// [`NodeIndex`] values (`idx.0.to_be_bytes()`), in this order:
///
/// 1. Classes trie — `len(classes_sorted)` then each class leaf index (already sorted).
/// 2. Contracts trie — `len(contracts_sorted)` then each contract leaf index (already sorted).
/// 3. Storage tries — `len(storage_sorted)` then, for each contract index in ascending order: the
/// contract index, `len(storage slot indices)` for that contract, then each storage slot index
/// (already sorted within the contract).
#[cfg(feature = "os_input")]
pub fn accessed_keys_digest(sorted: &SortedLeavesRequest<'_>) -> [u8; 32] {
let mut payload = Vec::new();

let class = sorted.class_sorted.get_indices();
payload.extend_from_slice(&encode_usize(class.len()));
for idx in class {
payload.extend_from_slice(&idx.0.to_be_bytes());
}

let contract = sorted.contract_sorted.get_indices();
payload.extend_from_slice(&encode_usize(contract.len()));
for idx in contract {
payload.extend_from_slice(&idx.0.to_be_bytes());
}

let mut contract_indices: Vec<NodeIndex> = sorted.storage_sorted.keys().copied().collect();
contract_indices.sort_unstable();

payload.extend_from_slice(&encode_usize(contract_indices.len()));
for contract_idx in contract_indices {
let sorted_slots = sorted.storage_sorted.get(&contract_idx).unwrap();
payload.extend_from_slice(&contract_idx.0.to_be_bytes());
let slot_indices = sorted_slots.get_indices();
payload.extend_from_slice(&encode_usize(slot_indices.len()));
for slot in slot_indices {
payload.extend_from_slice(&slot.0.to_be_bytes());
}
}

Blake2s256::digest(&payload).into()
}

#[cfg(feature = "os_input")]
fn encode_usize(n: usize) -> [u8; 8] {
u64::try_from(n).expect("accessed leaf count exceeds u64::MAX").to_be_bytes()
}
1 change: 1 addition & 0 deletions crates/starknet_committer/src/patricia_merkle_tree/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct LeavesRequest {
pub struct SortedLeavesRequest<'a> {
pub class_sorted: SortedLeafIndices<'a>,
pub contract_sorted: SortedLeafIndices<'a>,
// TODO(Ariel): use BTreeMap here and in fetch_all_patricia_paths.
pub storage_sorted: HashMap<NodeIndex, SortedLeafIndices<'a>>,
}

Expand Down
Loading