Skip to content

Commit 62dcd79

Browse files
committed
feat: cachingdb traits
1 parent e1a5fa7 commit 62dcd79

File tree

4 files changed

+116
-32
lines changed

4 files changed

+116
-32
lines changed

src/db/cow/mod.rs

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::db::CachingDb;
12
use alloy::{
23
consensus::constants::KECCAK_EMPTY,
34
primitives::{Address, B256, U256},
@@ -10,6 +11,8 @@ use revm::{
1011
Database, DatabaseCommit, DatabaseRef,
1112
};
1213

14+
use super::TryCachingDb;
15+
1316
/// A version of [`CacheDB`] that caches only on write, not on read.
1417
///
1518
/// This saves memory when wrapping some other caching database, like [`State`]
@@ -49,11 +52,21 @@ impl<Db> CacheOnWrite<Db> {
4952
&self.inner
5053
}
5154

55+
/// Get a mutable reference to the inner database.
56+
pub const fn inner_mut(&mut self) -> &mut Db {
57+
&mut self.inner
58+
}
59+
5260
/// Get a refernce to the [`Cache`].
5361
pub const fn cache(&self) -> &Cache {
5462
&self.cache
5563
}
5664

65+
/// Get a mutable reference to the [`Cache`].
66+
pub const fn cache_mut(&mut self) -> &mut Cache {
67+
&mut self.cache
68+
}
69+
5770
/// Deconstruct the `CacheOnWrite` into its parts.
5871
pub fn into_parts(self) -> (Db, Cache) {
5972
(self.inner, self.cache)
@@ -91,29 +104,67 @@ impl<Db> CacheOnWrite<Db> {
91104
}
92105
}
93106

94-
impl<Db> CacheOnWrite<CacheOnWrite<Db>> {
95-
/// Discard the outer cache, returning the inner.
96-
pub fn discard_outer(self) -> CacheOnWrite<Db> {
97-
self.inner
107+
impl<Db> CachingDb for CacheOnWrite<Db> {
108+
fn cache(&self) -> &Cache {
109+
&self.cache
110+
}
111+
112+
fn cache_mut(&mut self) -> &mut Cache {
113+
&mut self.cache
98114
}
99115

116+
fn into_cache(self) -> Cache {
117+
self.cache
118+
}
119+
}
120+
121+
impl<Db> CacheOnWrite<Db>
122+
where
123+
Db: CachingDb,
124+
{
100125
/// Flattens a nested cache by applying the outer cache to the inner cache.
101126
///
102127
/// The behavior is as follows:
103128
/// - Accounts are overridden with outer accounts
104129
/// - Contracts are overridden with outer contracts
105130
/// - Block hashes are overridden with outer block hashes
106-
pub fn flatten(self) -> CacheOnWrite<Db> {
131+
pub fn flatten(self) -> Db {
107132
let Self { cache: Cache { accounts, contracts, logs, block_hashes }, mut inner } = self;
108133

109-
inner.cache.accounts.extend(accounts);
110-
inner.cache.contracts.extend(contracts);
111-
inner.cache.logs.extend(logs);
112-
inner.cache.block_hashes.extend(block_hashes);
134+
let inner_cache = inner.cache_mut();
135+
136+
inner_cache.accounts.extend(accounts);
137+
inner_cache.contracts.extend(contracts);
138+
inner_cache.logs.extend(logs);
139+
inner_cache.block_hashes.extend(block_hashes);
113140
inner
114141
}
115142
}
116143

144+
impl<Db> CacheOnWrite<Db>
145+
where
146+
Db: TryCachingDb,
147+
{
148+
/// Attempts to flatten a nested cache by applying the outer cache to the
149+
/// inner cache. This is a fallible version of [`CacheOnWrite::flatten`].
150+
///
151+
/// The behavior is as follows:
152+
/// - Accounts are overridden with outer accounts
153+
/// - Contracts are overridden with outer contracts
154+
/// - Block hashes are overridden with outer block hashes
155+
pub fn try_flatten(self) -> Result<Db, Db::Error> {
156+
let Self { cache: Cache { accounts, contracts, logs, block_hashes }, mut inner } = self;
157+
158+
let inner_cache = inner.try_cache_mut()?;
159+
160+
inner_cache.accounts.extend(accounts);
161+
inner_cache.contracts.extend(contracts);
162+
inner_cache.logs.extend(logs);
163+
inner_cache.block_hashes.extend(block_hashes);
164+
Ok(inner)
165+
}
166+
}
167+
117168
impl<Db: DatabaseRef> Database for CacheOnWrite<Db> {
118169
type Error = Db::Error;
119170

src/db/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub mod sync;
44

55
/// Database abstraction traits.
66
mod traits;
7-
pub use traits::{ArcUpgradeError, StateAcc, TryDatabaseCommit, TryStateAcc};
7+
pub use traits::{ArcUpgradeError, CachingDb, StateAcc, TryCachingDb, TryStateAcc};
88

99
/// Cache-on-write database. A memory cache that caches only on write, not on
1010
/// read. Intended to wrap some other caching database.

src/db/traits.rs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use revm::{
2-
database::{states::bundle_state::BundleRetention, BundleState, State},
3-
primitives::{Address, B256},
4-
state::Account,
5-
Database, DatabaseCommit,
2+
database::{states::bundle_state::BundleRetention, BundleState, Cache, CacheDB, State},
3+
primitives::B256,
4+
Database,
65
};
76
use std::{collections::BTreeMap, convert::Infallible, sync::Arc};
87

@@ -145,29 +144,63 @@ where
145144
}
146145
}
147146

148-
/// A fallible version of [`DatabaseCommit`].
149-
pub trait TryDatabaseCommit {
150-
/// Error type to be thrown when committing changes fails.
147+
/// Trait for Databases that have a [`Cache`].
148+
pub trait CachingDb {
149+
/// Get the cache.
150+
fn cache(&self) -> &Cache;
151+
152+
/// Get the cache mutably.
153+
fn cache_mut(&mut self) -> &mut Cache;
154+
155+
/// Deconstruct into the cache
156+
fn into_cache(self) -> Cache;
157+
}
158+
159+
impl<Db> CachingDb for CacheDB<Db> {
160+
fn cache(&self) -> &Cache {
161+
&self.cache
162+
}
163+
164+
fn cache_mut(&mut self) -> &mut Cache {
165+
&mut self.cache
166+
}
167+
168+
fn into_cache(self) -> Cache {
169+
self.cache
170+
}
171+
}
172+
173+
/// Trait for Databases that have a [`Cache`] and can fail to mutably access
174+
/// it. E.g. `Arc<CacheDB<Db>>`
175+
pub trait TryCachingDb {
176+
/// Error type to be thrown when cache access fails.
151177
type Error: core::error::Error;
152178

153-
/// Attempt to commit changes to the database.
154-
fn try_commit(
155-
&mut self,
156-
changes: revm::primitives::HashMap<Address, Account>,
157-
) -> Result<(), Self::Error>;
179+
/// Attempt to get the cache.
180+
fn cache(&self) -> &Cache;
181+
182+
/// Attempt to get the cache mutably.
183+
fn try_cache_mut(&mut self) -> Result<&mut Cache, Self::Error>;
184+
185+
/// Attempt to deconstruct into the cache
186+
fn try_into_cache(self) -> Result<Cache, Self::Error>;
158187
}
159188

160-
impl<Db> TryDatabaseCommit for Arc<Db>
189+
impl<Db> TryCachingDb for Arc<Db>
161190
where
162-
Db: DatabaseCommit,
191+
Db: CachingDb,
163192
{
164193
type Error = ArcUpgradeError;
165194

166-
fn try_commit(
167-
&mut self,
168-
changes: revm::primitives::HashMap<Address, Account>,
169-
) -> Result<(), Self::Error> {
170-
Self::get_mut(self).ok_or(ArcUpgradeError::NotUnique)?.commit(changes);
171-
Ok(())
195+
fn cache(&self) -> &Cache {
196+
self.as_ref().cache()
197+
}
198+
199+
fn try_cache_mut(&mut self) -> Result<&mut Cache, Self::Error> {
200+
Arc::get_mut(self).ok_or(ArcUpgradeError::NotUnique).map(|db| db.cache_mut())
201+
}
202+
203+
fn try_into_cache(self) -> Result<Cache, Self::Error> {
204+
Arc::into_inner(self).ok_or(ArcUpgradeError::NotUnique).map(|db| db.into_cache())
172205
}
173206
}

src/evm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
db::{StateAcc, TryDatabaseCommit, TryStateAcc},
2+
db::{StateAcc, TryStateAcc},
33
driver::DriveBlockResult,
44
helpers::{Ctx, Evm},
55
Block, BlockDriver, BundleDriver, Cfg, ChainDriver, DriveBundleResult, DriveChainResult,
@@ -16,7 +16,7 @@ use revm::{
1616
result::{EVMError, ExecutionResult, InvalidTransaction, ResultAndState},
1717
Block as _, BlockEnv, Cfg as _, ContextSetters, ContextTr, Transaction as _, TxEnv,
1818
},
19-
database::{states::bundle_state::BundleRetention, BundleState},
19+
database::{states::bundle_state::BundleRetention, BundleState, TryDatabaseCommit},
2020
inspector::NoOpInspector,
2121
interpreter::gas::calculate_initial_tx_gas_for_tx,
2222
primitives::{hardfork::SpecId, TxKind},

0 commit comments

Comments
 (0)