Skip to content

Commit 59b51ce

Browse files
committed
starknet_committer: add index layout leaves
1 parent c700f80 commit 59b51ce

File tree

6 files changed

+222
-6
lines changed

6 files changed

+222
-6
lines changed

crates/starknet_committer/src/db.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod db_layout;
33
pub mod external_test_utils;
44
pub mod facts_db;
55
pub mod forest_trait;
6+
pub mod index_db;
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
use starknet_api::core::{ClassHash, Nonce};
2+
use starknet_api::hash::HashOutput;
3+
use starknet_patricia::patricia_merkle_tree::node_data::errors::LeafResult;
4+
use starknet_patricia::patricia_merkle_tree::node_data::leaf::Leaf;
5+
use starknet_patricia_storage::db_object::{DBObject, HasStaticPrefix};
6+
use starknet_patricia_storage::errors::DeserializationError;
7+
use starknet_patricia_storage::storage_trait::{DbKeyPrefix, DbValue};
8+
use starknet_types_core::felt::Felt;
9+
10+
use crate::block_committer::input::StarknetStorageValue;
11+
use crate::patricia_merkle_tree::leaf::leaf_impl::ContractState;
12+
use crate::patricia_merkle_tree::types::CompiledClassHash;
13+
14+
// Wrapper types for the leaves so that we can implement a different DBObject for them.
15+
#[derive(Clone, Debug, Default, Eq, PartialEq)]
16+
pub struct IndexLayoutContractState(pub ContractState);
17+
#[derive(Clone, Debug, Default, Eq, PartialEq)]
18+
pub struct IndexLayoutCompiledClassHash(pub CompiledClassHash);
19+
#[derive(Clone, Debug, Default, Eq, PartialEq)]
20+
pub struct IndexLayoutStarknetStorageValue(pub StarknetStorageValue);
21+
22+
impl From<IndexLayoutContractState> for ContractState {
23+
fn from(index_layout_contract_state: IndexLayoutContractState) -> Self {
24+
index_layout_contract_state.0
25+
}
26+
}
27+
28+
impl AsRef<ContractState> for IndexLayoutContractState {
29+
fn as_ref(&self) -> &ContractState {
30+
&self.0
31+
}
32+
}
33+
34+
impl From<StarknetStorageValue> for IndexLayoutStarknetStorageValue {
35+
fn from(starknet_storage_value: StarknetStorageValue) -> Self {
36+
IndexLayoutStarknetStorageValue(starknet_storage_value)
37+
}
38+
}
39+
40+
impl From<CompiledClassHash> for IndexLayoutCompiledClassHash {
41+
fn from(compiled_class_hash: CompiledClassHash) -> Self {
42+
IndexLayoutCompiledClassHash(compiled_class_hash)
43+
}
44+
}
45+
46+
impl AsRef<CompiledClassHash> for IndexLayoutCompiledClassHash {
47+
fn as_ref(&self) -> &CompiledClassHash {
48+
&self.0
49+
}
50+
}
51+
52+
#[derive(Debug, PartialEq)]
53+
pub enum TrieType {
54+
ContractsTrie,
55+
ClassesTrie,
56+
StorageTrie(Felt),
57+
}
58+
59+
impl From<&TrieType> for DbKeyPrefix {
60+
fn from(trie_type: &TrieType) -> Self {
61+
match trie_type {
62+
TrieType::ContractsTrie => DbKeyPrefix::new(b"CONTRACTS_TREE_PREFIX"),
63+
TrieType::ClassesTrie => DbKeyPrefix::new(b"CLASSES_TREE_PREFIX"),
64+
TrieType::StorageTrie(contract_address) => {
65+
DbKeyPrefix::new(&(contract_address).to_bytes_be())
66+
}
67+
}
68+
}
69+
}
70+
71+
// TODO(Ariel): Remove this macro when HasStaticPrefix is a local trait. Replace with a blanket
72+
// impl for any type that implements some dummy IndexLayoutStaticPrefix trait.
73+
macro_rules! impl_has_static_prefix_for_index_layouts {
74+
($($ty:ty),* $(,)?) => {
75+
$(
76+
impl HasStaticPrefix for $ty {
77+
type KeyContext = TrieType;
78+
fn get_static_prefix(key_context: &Self::KeyContext) -> DbKeyPrefix {
79+
key_context.into()
80+
}
81+
}
82+
)*
83+
};
84+
}
85+
86+
impl_has_static_prefix_for_index_layouts! {
87+
IndexLayoutContractState,
88+
IndexLayoutCompiledClassHash,
89+
IndexLayoutStarknetStorageValue,
90+
}
91+
92+
macro_rules! impl_leaf_for_wrappers {
93+
($($wrapper:ty => $inner:ty),+ $(,)?) => {
94+
$(
95+
impl Leaf for $wrapper {
96+
type Input = <$inner as Leaf>::Input;
97+
type Output = <$inner as Leaf>::Output;
98+
99+
fn is_empty(&self) -> bool {
100+
// assumes `pub struct Wrapper(pub Inner);`
101+
self.0.is_empty()
102+
}
103+
104+
async fn create(
105+
input: Self::Input,
106+
) -> LeafResult<(Self, Self::Output)> {
107+
let (inner, output) = <$inner as Leaf>::create(input).await?;
108+
Ok((Self(inner), output))
109+
}
110+
}
111+
)+
112+
};
113+
}
114+
115+
impl_leaf_for_wrappers!(
116+
IndexLayoutContractState => ContractState,
117+
IndexLayoutStarknetStorageValue => StarknetStorageValue,
118+
IndexLayoutCompiledClassHash => CompiledClassHash,
119+
);
120+
121+
#[derive(Debug)]
122+
pub struct IndexLayoutLeafDeserializationError(pub &'static str);
123+
124+
impl std::fmt::Display for IndexLayoutLeafDeserializationError {
125+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126+
write!(f, "{}", self.0)
127+
}
128+
}
129+
impl std::error::Error for IndexLayoutLeafDeserializationError {}
130+
131+
impl DBObject for IndexLayoutContractState {
132+
type DeserializeContext = ();
133+
fn serialize(&self) -> DbValue {
134+
let mut buffer = Vec::new();
135+
self.0.class_hash.0.serialize(&mut buffer).unwrap();
136+
self.0.storage_root_hash.0.serialize(&mut buffer).unwrap();
137+
self.0.nonce.0.serialize(&mut buffer).unwrap();
138+
DbValue(buffer)
139+
}
140+
141+
fn deserialize(
142+
value: &DbValue,
143+
_deserialize_context: &Self::DeserializeContext,
144+
) -> Result<Self, DeserializationError> {
145+
let mut cursor: &[u8] = &value.0;
146+
let error_msg = "failed to deserialize ContractState from index DB";
147+
let class_hash = Felt::deserialize(&mut cursor).ok_or(DeserializationError::ValueError(
148+
Box::new(IndexLayoutLeafDeserializationError(error_msg)),
149+
))?;
150+
let storage_root_hash =
151+
Felt::deserialize(&mut cursor).ok_or(DeserializationError::ValueError(Box::new(
152+
IndexLayoutLeafDeserializationError(error_msg),
153+
)))?;
154+
let nonce = Felt::deserialize(&mut cursor).ok_or(DeserializationError::ValueError(
155+
Box::new(IndexLayoutLeafDeserializationError(error_msg)),
156+
))?;
157+
Ok(IndexLayoutContractState(ContractState {
158+
class_hash: ClassHash(class_hash),
159+
storage_root_hash: HashOutput(storage_root_hash),
160+
nonce: Nonce(nonce),
161+
}))
162+
}
163+
}
164+
165+
impl DBObject for IndexLayoutCompiledClassHash {
166+
type DeserializeContext = ();
167+
fn serialize(&self) -> DbValue {
168+
let mut buffer = Vec::new();
169+
self.0.0.serialize(&mut buffer).unwrap();
170+
DbValue(buffer)
171+
}
172+
fn deserialize(
173+
value: &DbValue,
174+
_deserialize_context: &Self::DeserializeContext,
175+
) -> Result<Self, DeserializationError> {
176+
Ok(CompiledClassHash(Felt::deserialize(&mut &value.0[..]).ok_or(
177+
DeserializationError::ValueError(Box::new(IndexLayoutLeafDeserializationError(
178+
"failed to deserialize CompiledClassHash from index DB",
179+
))),
180+
)?)
181+
.into())
182+
}
183+
}
184+
185+
impl DBObject for IndexLayoutStarknetStorageValue {
186+
type DeserializeContext = ();
187+
fn serialize(&self) -> DbValue {
188+
let mut buffer = Vec::new();
189+
self.0.0.serialize(&mut buffer).unwrap();
190+
DbValue(buffer)
191+
}
192+
fn deserialize(
193+
value: &DbValue,
194+
_deserialize_context: &Self::DeserializeContext,
195+
) -> Result<Self, DeserializationError> {
196+
Ok(IndexLayoutStarknetStorageValue(
197+
Felt::deserialize(&mut &value.0[..]).map(StarknetStorageValue).ok_or(
198+
DeserializationError::ValueError(Box::new(IndexLayoutLeafDeserializationError(
199+
"failed to deserialize StarknetStorageValue from index DB",
200+
))),
201+
)?,
202+
))
203+
}
204+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod leaves;

crates/starknet_committer/src/patricia_merkle_tree/leaf/leaf_impl.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ pub struct ContractState {
2020
pub storage_root_hash: HashOutput,
2121
pub class_hash: ClassHash,
2222
}
23-
23+
impl AsRef<ContractState> for ContractState {
24+
fn as_ref(&self) -> &ContractState {
25+
self
26+
}
27+
}
2428
impl HasStaticPrefix for StarknetStorageValue {
2529
type KeyContext = ();
2630
fn get_static_prefix(_key_context: &Self::KeyContext) -> DbKeyPrefix {

crates/starknet_committer/src/patricia_merkle_tree/types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ pub fn class_hash_into_node_index(class_hash: &ClassHash) -> NodeIndex {
2323
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
2424
pub struct CompiledClassHash(pub Felt);
2525

26+
impl AsRef<CompiledClassHash> for CompiledClassHash {
27+
fn as_ref(&self) -> &CompiledClassHash {
28+
self
29+
}
30+
}
31+
2632
impl_from_hex_for_felt_wrapper!(CompiledClassHash);
2733

2834
pub type StorageTrie = FilledTreeImpl<StarknetStorageValue>;

crates/starknet_patricia_storage/src/storage_trait.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,15 @@ impl Storage for NullStorage {
172172
}
173173

174174
#[derive(Debug)]
175-
pub struct DbKeyPrefix(&'static [u8]);
175+
pub struct DbKeyPrefix(Vec<u8>);
176176

177177
impl DbKeyPrefix {
178-
pub fn new(prefix: &'static [u8]) -> Self {
179-
Self(prefix)
178+
pub fn new(prefix: &[u8]) -> Self {
179+
Self(prefix.to_vec())
180180
}
181181

182-
pub fn to_bytes(&self) -> &'static [u8] {
183-
self.0
182+
pub fn to_bytes(&self) -> &[u8] {
183+
self.0.as_slice()
184184
}
185185
}
186186

0 commit comments

Comments
 (0)