Skip to content

Commit 0f53d18

Browse files
starknet_patricia_storage: split storage trait (#13234)
1 parent 2830204 commit 0f53d18

7 files changed

Lines changed: 109 additions & 86 deletions

File tree

crates/starknet_committer/src/db/index_db/test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use starknet_patricia::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndice
1313
use starknet_patricia::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunction;
1414
use starknet_patricia_storage::db_object::{DBObject, EmptyKeyContext, HasStaticPrefix};
1515
use starknet_patricia_storage::map_storage::MapStorage;
16-
use starknet_patricia_storage::storage_trait::{DbHashMap, DbValue, Storage};
16+
use starknet_patricia_storage::storage_trait::{DbHashMap, DbValue, ReadOnlyStorage, Storage};
1717

1818
use crate::block_committer::input::try_node_index_into_contract_address;
1919
use crate::db::db_layout::DbLayout;

crates/starknet_patricia_storage/src/aerospike_storage.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::storage_trait::{
3535
EmptyStorageConfig,
3636
NoStats,
3737
PatriciaStorageResult,
38+
ReadOnlyStorage,
3839
Storage,
3940
};
4041

@@ -128,10 +129,7 @@ impl AerospikeStorage {
128129
}
129130
}
130131

131-
impl Storage for AerospikeStorage {
132-
type Stats = NoStats;
133-
type Config = EmptyStorageConfig;
134-
132+
impl ReadOnlyStorage for AerospikeStorage {
135133
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
136134
let record = self
137135
.client
@@ -140,17 +138,6 @@ impl Storage for AerospikeStorage {
140138
self.extract_value(&record)
141139
}
142140

143-
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
144-
Ok(self
145-
.client
146-
.put(
147-
&self.config.write_policy,
148-
&self.get_key(key)?,
149-
&[as_bin!(&self.config.bin_name, value.0)],
150-
)
151-
.await?)
152-
}
153-
154141
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
155142
let mut ops = Vec::new();
156143
for key in keys.iter() {
@@ -174,6 +161,22 @@ impl Storage for AerospikeStorage {
174161
})
175162
.collect::<Result<_, _>>()
176163
}
164+
}
165+
166+
impl Storage for AerospikeStorage {
167+
type Stats = NoStats;
168+
type Config = EmptyStorageConfig;
169+
170+
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
171+
Ok(self
172+
.client
173+
.put(
174+
&self.config.write_policy,
175+
&self.get_key(key)?,
176+
&[as_bin!(&self.config.bin_name, value.0)],
177+
)
178+
.await?)
179+
}
177180

178181
async fn mset(&mut self, key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
179182
let keys_and_bins: Vec<(DbKey, Bin)> = key_to_value

crates/starknet_patricia_storage/src/map_storage.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::storage_trait::{
1919
NoStats,
2020
NullStorage,
2121
PatriciaStorageResult,
22+
ReadOnlyStorage,
2223
Storage,
2324
StorageConfigTrait,
2425
StorageStats,
@@ -35,6 +36,16 @@ pub struct BorrowedStorage<'a, S: Storage> {
3536
pub storage: &'a mut S,
3637
}
3738

39+
impl ReadOnlyStorage for MapStorage {
40+
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
41+
Ok(self.0.get(key).cloned())
42+
}
43+
44+
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
45+
Ok(keys.iter().map(|key| self.0.get(key).cloned()).collect())
46+
}
47+
}
48+
3849
impl Storage for MapStorage {
3950
type Stats = NoStats;
4051
type Config = EmptyStorageConfig;
@@ -67,14 +78,6 @@ impl Storage for MapStorage {
6778
Ok(())
6879
}
6980

70-
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
71-
Ok(self.0.get(key).cloned())
72-
}
73-
74-
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
75-
Ok(keys.iter().map(|key| self.0.get(key).cloned()).collect())
76-
}
77-
7881
fn get_stats(&self) -> PatriciaStorageResult<Self::Stats> {
7982
Ok(NoStats)
8083
}
@@ -251,10 +254,7 @@ impl<S: Storage> CachedStorage<S> {
251254
}
252255
}
253256

254-
impl<S: Storage> Storage for CachedStorage<S> {
255-
type Stats = CachedStorageStats<S::Stats>;
256-
type Config = CachedStorageConfig<S::Config>;
257-
257+
impl<S: Storage> ReadOnlyStorage for CachedStorage<S> {
258258
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
259259
self.reads += 1;
260260
if let Some(cached_value) = self.cache.get(key) {
@@ -267,13 +267,6 @@ impl<S: Storage> Storage for CachedStorage<S> {
267267
Ok(storage_value)
268268
}
269269

270-
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
271-
self.writes += 1;
272-
self.storage.set(key.clone(), value.clone()).await?;
273-
self.update_cached_value(&key, &value);
274-
Ok(())
275-
}
276-
277270
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
278271
let mut values = vec![None; keys.len()]; // The None values are placeholders.
279272
let mut keys_to_fetch = Vec::new();
@@ -302,6 +295,18 @@ impl<S: Storage> Storage for CachedStorage<S> {
302295

303296
Ok(values)
304297
}
298+
}
299+
300+
impl<S: Storage> Storage for CachedStorage<S> {
301+
type Stats = CachedStorageStats<S::Stats>;
302+
type Config = CachedStorageConfig<S::Config>;
303+
304+
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
305+
self.writes += 1;
306+
self.storage.set(key.clone(), value.clone()).await?;
307+
self.update_cached_value(&key, &value);
308+
Ok(())
309+
}
305310

306311
async fn mset(&mut self, key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
307312
self.writes += u128::try_from(key_to_value.len()).expect("usize should fit in u128");

crates/starknet_patricia_storage/src/mdbx_storage.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::storage_trait::{
2323
DbValue,
2424
EmptyStorageConfig,
2525
PatriciaStorageResult,
26+
ReadOnlyStorage,
2627
Storage,
2728
StorageStats,
2829
};
@@ -103,24 +104,13 @@ impl MdbxStorage {
103104
}
104105
}
105106

106-
impl Storage for MdbxStorage {
107-
type Stats = MdbxStorageStats;
108-
type Config = EmptyStorageConfig;
109-
107+
impl ReadOnlyStorage for MdbxStorage {
110108
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
111109
let txn = self.db.begin_ro_txn()?;
112110
let table = txn.open_table(None)?;
113111
Ok(txn.get(&table, &key.0)?.map(DbValue))
114112
}
115113

116-
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
117-
let txn = self.db.begin_rw_txn()?;
118-
let table = txn.open_table(None)?;
119-
txn.put(&table, key.0, value.0, WriteFlags::UPSERT)?;
120-
txn.commit()?;
121-
Ok(())
122-
}
123-
124114
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
125115
let txn = self.db.begin_ro_txn()?;
126116
let table = txn.open_table(None)?;
@@ -130,6 +120,19 @@ impl Storage for MdbxStorage {
130120
}
131121
Ok(res)
132122
}
123+
}
124+
125+
impl Storage for MdbxStorage {
126+
type Stats = MdbxStorageStats;
127+
type Config = EmptyStorageConfig;
128+
129+
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
130+
let txn = self.db.begin_rw_txn()?;
131+
let table = txn.open_table(None)?;
132+
txn.put(&table, key.0, value.0, WriteFlags::UPSERT)?;
133+
txn.commit()?;
134+
Ok(())
135+
}
133136

134137
async fn mset(&mut self, key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
135138
let txn = self.db.begin_rw_txn()?;

crates/starknet_patricia_storage/src/rocksdb_storage.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::storage_trait::{
2828
DbValue,
2929
PatriciaStorageError,
3030
PatriciaStorageResult,
31+
ReadOnlyStorage,
3132
Storage,
3233
StorageConfigTrait,
3334
StorageStats,
@@ -275,18 +276,11 @@ impl StorageStats for RocksDbStats {
275276
}
276277
}
277278

278-
impl Storage for RocksDbStorage {
279-
type Stats = RocksDbStats;
280-
type Config = RocksDbStorageConfig;
281-
279+
impl ReadOnlyStorage for RocksDbStorage {
282280
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
283281
Ok(self.db.get(&key.0)?.map(DbValue))
284282
}
285283

286-
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
287-
Ok(self.db.put_opt(&key.0, &value.0, &self.options.write_options)?)
288-
}
289-
290284
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
291285
let raw_keys = keys.iter().map(|k| &k.0);
292286
let res = self
@@ -297,6 +291,15 @@ impl Storage for RocksDbStorage {
297291
.collect::<Result<_, _>>()?;
298292
Ok(res)
299293
}
294+
}
295+
296+
impl Storage for RocksDbStorage {
297+
type Stats = RocksDbStats;
298+
type Config = RocksDbStorageConfig;
299+
300+
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
301+
Ok(self.db.put_opt(&key.0, &value.0, &self.options.write_options)?)
302+
}
300303

301304
async fn mset(&mut self, key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
302305
let mut batch = WriteBatch::default();

crates/starknet_patricia_storage/src/short_key_storage.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::storage_trait::{
1111
DbValue,
1212
EmptyStorageConfig,
1313
PatriciaStorageResult,
14+
ReadOnlyStorage,
1415
Storage,
1516
};
1617

@@ -47,25 +48,27 @@ macro_rules! define_short_key_storage {
4748
}
4849
}
4950

50-
impl<S: Storage> Storage for $name<S> {
51-
type Stats = S::Stats;
52-
type Config = EmptyStorageConfig;
53-
51+
impl<S: Storage> ReadOnlyStorage for $name<S> {
5452
async fn get(&mut self, key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
5553
self.storage.get(&Self::small_key(key)).await
5654
}
5755

58-
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
59-
self.storage.set(Self::small_key(&key), value).await
60-
}
61-
6256
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
6357
let small_keys = keys
6458
.iter()
6559
.map(|key| Self::small_key(key))
6660
.collect::<Vec<_>>();
6761
self.storage.mget(small_keys.iter().collect::<Vec<&DbKey>>().as_slice()).await
6862
}
63+
}
64+
65+
impl<S: Storage> Storage for $name<S> {
66+
type Stats = S::Stats;
67+
type Config = EmptyStorageConfig;
68+
69+
async fn set(&mut self, key: DbKey, value: DbValue) -> PatriciaStorageResult<()> {
70+
self.storage.set(Self::small_key(&key), value).await
71+
}
6972

7073
async fn mset(&mut self, key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
7174
self.storage.mset(

crates/starknet_patricia_storage/src/storage_trait.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,11 @@ pub trait StorageConfigTrait:
9999
Clone + Debug + Serialize + PartialEq + Validate + SerializeConfig + Default + Send + Sync
100100
{
101101
}
102-
/// A trait for the storage. Does not assume concurrent access is possible - see [AsyncStorage].
103-
pub trait Storage: Send + Sync {
104-
type Stats: StorageStats;
105-
type Config: StorageConfigTrait;
106102

103+
/// A read-only view of a storage. Does not assume concurrent access is possible.
104+
pub trait ReadOnlyStorage: Send + Sync {
107105
/// Returns value from storage, if it exists.
108-
/// Uses a mutable &self to allow changes in the internal state of the storage (e.g.,
106+
/// Uses a mutable `&self` to allow changes in the internal state of the storage (e.g.,
109107
/// for caching).
110108
// Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see
111109
// https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#async-fn-in-public-traits
@@ -115,16 +113,6 @@ pub trait Storage: Send + Sync {
115113
key: &DbKey,
116114
) -> impl Future<Output = PatriciaStorageResult<Option<DbValue>>> + Send;
117115

118-
/// Sets value in storage. If key already exists, its value is overwritten.
119-
// Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see
120-
// https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#async-fn-in-public-traits
121-
// for details.
122-
fn set(
123-
&mut self,
124-
key: DbKey,
125-
value: DbValue,
126-
) -> impl Future<Output = PatriciaStorageResult<()>> + Send;
127-
128116
/// Returns values from storage in same order of given keys. Value is None for keys that do not
129117
/// exist.
130118
// Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see
@@ -134,6 +122,22 @@ pub trait Storage: Send + Sync {
134122
&mut self,
135123
keys: &[&DbKey],
136124
) -> impl Future<Output = PatriciaStorageResult<Vec<Option<DbValue>>>> + Send;
125+
}
126+
127+
/// A trait for the storage. Extends [ReadOnlyStorage] with write operations.
128+
pub trait Storage: ReadOnlyStorage {
129+
type Stats: StorageStats;
130+
type Config: StorageConfigTrait;
131+
132+
/// Sets value in storage. If key already exists, its value is overwritten.
133+
// Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see
134+
// https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#async-fn-in-public-traits
135+
// for details.
136+
fn set(
137+
&mut self,
138+
key: DbKey,
139+
value: DbValue,
140+
) -> impl Future<Output = PatriciaStorageResult<()>> + Send;
137141

138142
/// Sets values in storage.
139143
// Use explicit desugaring of `async fn` to allow adding trait bounds to the return type, see
@@ -198,21 +202,23 @@ impl StorageConfigTrait for EmptyStorageConfig {}
198202
#[derive(Clone)]
199203
pub struct NullStorage;
200204

201-
impl Storage for NullStorage {
202-
type Stats = NoStats;
203-
type Config = EmptyStorageConfig;
204-
205+
impl ReadOnlyStorage for NullStorage {
205206
async fn get(&mut self, _key: &DbKey) -> PatriciaStorageResult<Option<DbValue>> {
206207
Ok(None)
207208
}
208209

209-
async fn set(&mut self, _key: DbKey, _value: DbValue) -> PatriciaStorageResult<()> {
210-
Ok(())
211-
}
212-
213210
async fn mget(&mut self, keys: &[&DbKey]) -> PatriciaStorageResult<Vec<Option<DbValue>>> {
214211
Ok(vec![None; keys.len()])
215212
}
213+
}
214+
215+
impl Storage for NullStorage {
216+
type Stats = NoStats;
217+
type Config = EmptyStorageConfig;
218+
219+
async fn set(&mut self, _key: DbKey, _value: DbValue) -> PatriciaStorageResult<()> {
220+
Ok(())
221+
}
216222

217223
async fn mset(&mut self, _key_to_value: DbHashMap) -> PatriciaStorageResult<()> {
218224
Ok(())

0 commit comments

Comments
 (0)