Make triecache generic and work for no-std environments (#14403)

* Remove `AsLocalTrieCache` trait

* Introduce new trait AsTrieDbCache

* Use AsTrieDbCache trait

* Make it compile

* Docs

* Improve naming of associated type, implement cache usage for no-std

* Improve naming

* Improve docs

* Allow construction with optional cache

* FMT

* Remove unused variable

* Revert unwanted change

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <git@kchr.de>

* More comment adjustments

* Docs

* Trigger CI

* ".git/.scripts/commands/fmt/fmt.sh"

* Apply suggestions from code review

Co-authored-by: Koute <koute@users.noreply.github.com>

* Review comments

* Review comments

* Apply suggestions from code review

Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>

* fmt

* Bump trie-db again

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: command-bot <>
Co-authored-by: Koute <koute@users.noreply.github.com>
Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
This commit is contained in:
Sebastian Kunert
2023-06-28 14:57:41 +02:00
committed by GitHub
parent 943697fa69
commit 30a7e6788c
5 changed files with 185 additions and 95 deletions
@@ -27,13 +27,13 @@ sp-externalities = { version = "0.19.0", default-features = false, path = "../ex
sp-panic-handler = { version = "8.0.0", optional = true, path = "../panic-handler" } sp-panic-handler = { version = "8.0.0", optional = true, path = "../panic-handler" }
sp-std = { version = "8.0.0", default-features = false, path = "../std" } sp-std = { version = "8.0.0", default-features = false, path = "../std" }
sp-trie = { version = "22.0.0", default-features = false, path = "../trie" } sp-trie = { version = "22.0.0", default-features = false, path = "../trie" }
trie-db = { version = "0.27.1", default-features = false }
[dev-dependencies] [dev-dependencies]
array-bytes = "4.1" array-bytes = "4.1"
pretty_assertions = "1.2.1" pretty_assertions = "1.2.1"
rand = "0.8.5" rand = "0.8.5"
sp-runtime = { version = "24.0.0", path = "../runtime" } sp-runtime = { version = "24.0.0", path = "../runtime" }
trie-db = "0.27.1"
assert_matches = "1.5" assert_matches = "1.5"
[features] [features]
@@ -49,6 +49,7 @@ std = [
"sp-panic-handler", "sp-panic-handler",
"sp-std/std", "sp-std/std",
"sp-trie/std", "sp-trie/std",
"trie-db/std",
"thiserror", "thiserror",
"tracing", "tracing",
] ]
@@ -36,6 +36,8 @@ mod testing;
mod trie_backend; mod trie_backend;
mod trie_backend_essence; mod trie_backend_essence;
pub use trie_backend::TrieCacheProvider;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std_reexport::*; pub use std_reexport::*;
@@ -24,61 +24,142 @@ use crate::{
trie_backend_essence::{RawIter, TrieBackendEssence, TrieBackendStorage}, trie_backend_essence::{RawIter, TrieBackendEssence, TrieBackendStorage},
Backend, StorageKey, StorageValue, Backend, StorageKey, StorageValue,
}; };
use codec::Codec; use codec::Codec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use hash_db::HashDB; use hash_db::HashDB;
use hash_db::Hasher; use hash_db::Hasher;
use sp_core::storage::{ChildInfo, StateVersion}; use sp_core::storage::{ChildInfo, StateVersion};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sp_trie::{cache::LocalTrieCache, recorder::Recorder}; use sp_trie::{
#[cfg(feature = "std")] cache::{LocalTrieCache, TrieCache},
use sp_trie::{MemoryDB, StorageProof}; recorder::Recorder,
MemoryDB, StorageProof,
/// Dummy type to be used in `no_std`. };
///
/// This is required to have the type available for [`TrieBackendBuilder`] and [`TrieBackend`].
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
pub struct LocalTrieCache<H>(sp_std::marker::PhantomData<H>); use sp_trie::{Error, NodeCodec};
use trie_db::TrieCache as TrieCacheT;
#[cfg(not(feature = "std"))]
use trie_db::{node::NodeOwned, CachedValue};
/// Special trait to support taking the [`LocalTrieCache`] by value or by reference. /// A provider of trie caches that are compatible with [`trie_db::TrieDB`].
/// pub trait TrieCacheProvider<H: Hasher> {
/// This trait is internal use only and to emphasize this, the trait is sealed. /// Cache type that implements [`trie_db::TrieCache`].
pub trait AsLocalTrieCache<H: Hasher>: sealed::Sealed { type Cache<'a>: TrieCacheT<sp_trie::NodeCodec<H>> + 'a
/// Returns `self` as [`LocalTrieCache`]. where
#[cfg(feature = "std")] Self: 'a;
fn as_local_trie_cache(&self) -> &LocalTrieCache<H>;
/// Return a [`trie_db::TrieDB`] compatible cache.
///
/// The `storage_root` parameter should be the storage root of the used trie.
fn as_trie_db_cache(&self, storage_root: H::Out) -> Self::Cache<'_>;
/// Returns a cache that can be used with a [`trie_db::TrieDBMut`].
///
/// When finished with the operation on the trie, it is required to call [`Self::merge`] to
/// merge the cached items for the correct `storage_root`.
fn as_trie_db_mut_cache(&self) -> Self::Cache<'_>;
/// Merge the cached data in `other` into the provider using the given `new_root`.
///
/// This must be used for the cache returned by [`Self::as_trie_db_mut_cache`] as otherwise the
/// cached data is just thrown away.
fn merge<'a>(&'a self, other: Self::Cache<'a>, new_root: H::Out);
} }
impl<H: Hasher> AsLocalTrieCache<H> for LocalTrieCache<H> { #[cfg(feature = "std")]
#[cfg(feature = "std")] impl<H: Hasher> TrieCacheProvider<H> for LocalTrieCache<H> {
#[inline] type Cache<'a> = TrieCache<'a, H> where H: 'a;
fn as_local_trie_cache(&self) -> &LocalTrieCache<H> {
self fn as_trie_db_cache(&self, storage_root: H::Out) -> Self::Cache<'_> {
self.as_trie_db_cache(storage_root)
}
fn as_trie_db_mut_cache(&self) -> Self::Cache<'_> {
self.as_trie_db_mut_cache()
}
fn merge<'a>(&'a self, other: Self::Cache<'a>, new_root: H::Out) {
other.merge_into(self, new_root)
} }
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<H: Hasher> AsLocalTrieCache<H> for &LocalTrieCache<H> { impl<H: Hasher> TrieCacheProvider<H> for &LocalTrieCache<H> {
#[inline] type Cache<'a> = TrieCache<'a, H> where Self: 'a;
fn as_local_trie_cache(&self) -> &LocalTrieCache<H> {
self fn as_trie_db_cache(&self, storage_root: H::Out) -> Self::Cache<'_> {
(*self).as_trie_db_cache(storage_root)
}
fn as_trie_db_mut_cache(&self) -> Self::Cache<'_> {
(*self).as_trie_db_mut_cache()
}
fn merge<'a>(&'a self, other: Self::Cache<'a>, new_root: H::Out) {
other.merge_into(self, new_root)
} }
} }
/// Special module that contains the `Sealed` trait. /// Cache provider that allows construction of a [`TrieBackend`] and satisfies the requirements, but
mod sealed { /// can never be instantiated.
use super::*; #[cfg(not(feature = "std"))]
pub struct UnimplementedCacheProvider<H> {
/// A special trait which prevents externals to implement the [`AsLocalTrieCache`] outside // Not strictly necessary, but the H bound allows to use this as a drop-in
/// of this crate. // replacement for the `LocalTrieCache` in no-std contexts.
pub trait Sealed {} _phantom: core::marker::PhantomData<H>,
// Statically prevents construction.
impl<H: Hasher> Sealed for LocalTrieCache<H> {} _infallible: core::convert::Infallible,
impl<H: Hasher> Sealed for &LocalTrieCache<H> {}
} }
#[cfg(not(feature = "std"))]
impl<H: Hasher> trie_db::TrieCache<NodeCodec<H>> for UnimplementedCacheProvider<H> {
fn lookup_value_for_key(&mut self, _key: &[u8]) -> Option<&CachedValue<H::Out>> {
unimplemented!()
}
fn cache_value_for_key(&mut self, _key: &[u8], _value: CachedValue<H::Out>) {
unimplemented!()
}
fn get_or_insert_node(
&mut self,
_hash: H::Out,
_fetch_node: &mut dyn FnMut() -> trie_db::Result<NodeOwned<H::Out>, H::Out, Error<H::Out>>,
) -> trie_db::Result<&NodeOwned<H::Out>, H::Out, Error<H::Out>> {
unimplemented!()
}
fn get_node(&mut self, _hash: &H::Out) -> Option<&NodeOwned<H::Out>> {
unimplemented!()
}
}
#[cfg(not(feature = "std"))]
impl<H: Hasher> TrieCacheProvider<H> for UnimplementedCacheProvider<H> {
type Cache<'a> = UnimplementedCacheProvider<H> where H: 'a;
fn as_trie_db_cache(&self, _storage_root: <H as Hasher>::Out) -> Self::Cache<'_> {
unimplemented!()
}
fn as_trie_db_mut_cache(&self) -> Self::Cache<'_> {
unimplemented!()
}
fn merge<'a>(&'a self, _other: Self::Cache<'a>, _new_root: <H as Hasher>::Out) {
unimplemented!()
}
}
#[cfg(feature = "std")]
type DefaultCache<H> = LocalTrieCache<H>;
#[cfg(not(feature = "std"))]
type DefaultCache<H> = UnimplementedCacheProvider<H>;
/// Builder for creating a [`TrieBackend`]. /// Builder for creating a [`TrieBackend`].
pub struct TrieBackendBuilder<S: TrieBackendStorage<H>, H: Hasher, C = LocalTrieCache<H>> { pub struct TrieBackendBuilder<S: TrieBackendStorage<H>, H: Hasher, C = DefaultCache<H>> {
storage: S, storage: S,
root: H::Out, root: H::Out,
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -86,7 +167,7 @@ pub struct TrieBackendBuilder<S: TrieBackendStorage<H>, H: Hasher, C = LocalTrie
cache: Option<C>, cache: Option<C>,
} }
impl<S, H> TrieBackendBuilder<S, H, LocalTrieCache<H>> impl<S, H> TrieBackendBuilder<S, H, DefaultCache<H>>
where where
S: TrieBackendStorage<H>, S: TrieBackendStorage<H>,
H: Hasher, H: Hasher,
@@ -108,6 +189,16 @@ where
S: TrieBackendStorage<H>, S: TrieBackendStorage<H>,
H: Hasher, H: Hasher,
{ {
/// Create a new builder instance.
pub fn new_with_cache(storage: S, root: H::Out, cache: C) -> Self {
Self {
storage,
root,
#[cfg(feature = "std")]
recorder: None,
cache: Some(cache),
}
}
/// Wrap the given [`TrieBackend`]. /// Wrap the given [`TrieBackend`].
/// ///
/// This can be used for example if all accesses to the trie should /// This can be used for example if all accesses to the trie should
@@ -121,10 +212,7 @@ where
root: *other.essence.root(), root: *other.essence.root(),
#[cfg(feature = "std")] #[cfg(feature = "std")]
recorder: None, recorder: None,
#[cfg(feature = "std")]
cache: other.essence.trie_node_cache.as_ref(), cache: other.essence.trie_node_cache.as_ref(),
#[cfg(not(feature = "std"))]
cache: None,
} }
} }
@@ -141,23 +229,23 @@ where
} }
/// Use the given optional `cache` for the to be configured [`TrieBackend`]. /// Use the given optional `cache` for the to be configured [`TrieBackend`].
#[cfg(feature = "std")]
pub fn with_optional_cache<LC>(self, cache: Option<LC>) -> TrieBackendBuilder<S, H, LC> { pub fn with_optional_cache<LC>(self, cache: Option<LC>) -> TrieBackendBuilder<S, H, LC> {
TrieBackendBuilder { TrieBackendBuilder {
cache, cache,
root: self.root, root: self.root,
storage: self.storage, storage: self.storage,
#[cfg(feature = "std")]
recorder: self.recorder, recorder: self.recorder,
} }
} }
/// Use the given `cache` for the to be configured [`TrieBackend`]. /// Use the given `cache` for the to be configured [`TrieBackend`].
#[cfg(feature = "std")]
pub fn with_cache<LC>(self, cache: LC) -> TrieBackendBuilder<S, H, LC> { pub fn with_cache<LC>(self, cache: LC) -> TrieBackendBuilder<S, H, LC> {
TrieBackendBuilder { TrieBackendBuilder {
cache: Some(cache), cache: Some(cache),
root: self.root, root: self.root,
storage: self.storage, storage: self.storage,
#[cfg(feature = "std")]
recorder: self.recorder, recorder: self.recorder,
} }
} }
@@ -179,10 +267,8 @@ where
/// Build the configured [`TrieBackend`]. /// Build the configured [`TrieBackend`].
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
pub fn build(self) -> TrieBackend<S, H, C> { pub fn build(self) -> TrieBackend<S, H, C> {
let _ = self.cache;
TrieBackend { TrieBackend {
essence: TrieBackendEssence::new(self.storage, self.root), essence: TrieBackendEssence::new_with_cache(self.storage, self.root, self.cache),
next_storage_key_cache: Default::default(), next_storage_key_cache: Default::default(),
} }
} }
@@ -223,12 +309,13 @@ fn access_cache<T, R>(cell: &CacheCell<T>, callback: impl FnOnce(&mut T) -> R) -
} }
/// Patricia trie-based backend. Transaction type is an overlay of changes to commit. /// Patricia trie-based backend. Transaction type is an overlay of changes to commit.
pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher, C = LocalTrieCache<H>> { pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher, C = DefaultCache<H>> {
pub(crate) essence: TrieBackendEssence<S, H, C>, pub(crate) essence: TrieBackendEssence<S, H, C>,
next_storage_key_cache: CacheCell<Option<CachedIter<S, H, C>>>, next_storage_key_cache: CacheCell<Option<CachedIter<S, H, C>>>,
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> TrieBackend<S, H, C> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
TrieBackend<S, H, C>
where where
H::Out: Codec, H::Out: Codec,
{ {
@@ -276,7 +363,7 @@ where
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> sp_std::fmt::Debug impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H>> sp_std::fmt::Debug
for TrieBackend<S, H, C> for TrieBackend<S, H, C>
{ {
fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
@@ -284,7 +371,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> sp_std::fmt::D
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> Backend<H> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync> Backend<H>
for TrieBackend<S, H, C> for TrieBackend<S, H, C>
where where
H::Out: Ord + Codec, H::Out: Ord + Codec,
@@ -20,7 +20,7 @@
use crate::{ use crate::{
backend::{Consolidate, IterArgs, StorageIterator}, backend::{Consolidate, IterArgs, StorageIterator},
trie_backend::AsLocalTrieCache, trie_backend::TrieCacheProvider,
warn, StorageKey, StorageValue, warn, StorageKey, StorageValue,
}; };
use codec::Codec; use codec::Codec;
@@ -39,7 +39,6 @@ use sp_trie::{
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
// In this module, we only use layout for read operation and empty root, // In this module, we only use layout for read operation and empty root,
// where V1 and V0 are equivalent. // where V1 and V0 are equivalent.
use sp_trie::LayoutV1 as Layout; use sp_trie::LayoutV1 as Layout;
@@ -100,7 +99,7 @@ where
H: Hasher, H: Hasher,
S: TrieBackendStorage<H>, S: TrieBackendStorage<H>,
H::Out: Codec + Ord, H::Out: Codec + Ord,
C: AsLocalTrieCache<H> + Send + Sync, C: TrieCacheProvider<H> + Send + Sync,
{ {
#[inline] #[inline]
fn prepare<R>( fn prepare<R>(
@@ -160,7 +159,7 @@ where
H: Hasher, H: Hasher,
S: TrieBackendStorage<H>, S: TrieBackendStorage<H>,
H::Out: Codec + Ord, H::Out: Codec + Ord,
C: AsLocalTrieCache<H> + Send + Sync, C: TrieCacheProvider<H> + Send + Sync,
{ {
type Backend = crate::TrieBackend<S, H, C>; type Backend = crate::TrieBackend<S, H, C>;
type Error = crate::DefaultError; type Error = crate::DefaultError;
@@ -209,29 +208,28 @@ pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher, C> {
empty: H::Out, empty: H::Out,
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub(crate) cache: Arc<RwLock<Cache<H::Out>>>, pub(crate) cache: Arc<RwLock<Cache<H::Out>>>,
#[cfg(feature = "std")]
pub(crate) trie_node_cache: Option<C>, pub(crate) trie_node_cache: Option<C>,
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub(crate) recorder: Option<Recorder<H>>, pub(crate) recorder: Option<Recorder<H>>,
#[cfg(not(feature = "std"))]
_phantom: PhantomData<C>,
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C> TrieBackendEssence<S, H, C> { impl<S: TrieBackendStorage<H>, H: Hasher, C> TrieBackendEssence<S, H, C> {
/// Create new trie-based backend. /// Create new trie-based backend.
pub fn new(storage: S, root: H::Out) -> Self { pub fn new(storage: S, root: H::Out) -> Self {
Self::new_with_cache(storage, root, None)
}
/// Create new trie-based backend.
pub fn new_with_cache(storage: S, root: H::Out, cache: Option<C>) -> Self {
TrieBackendEssence { TrieBackendEssence {
storage, storage,
root, root,
empty: H::hash(&[0u8]), empty: H::hash(&[0u8]),
#[cfg(feature = "std")] #[cfg(feature = "std")]
cache: Arc::new(RwLock::new(Cache::new())), cache: Arc::new(RwLock::new(Cache::new())),
#[cfg(feature = "std")] trie_node_cache: cache,
trie_node_cache: None,
#[cfg(feature = "std")] #[cfg(feature = "std")]
recorder: None, recorder: None,
#[cfg(not(feature = "std"))]
_phantom: PhantomData,
} }
} }
@@ -289,11 +287,10 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C> TrieBackendEssence<S, H, C> {
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> TrieBackendEssence<S, H, C> { impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H>> TrieBackendEssence<S, H, C> {
/// Call the given closure passing it the recorder and the cache. /// Call the given closure passing it the recorder and the cache.
/// ///
/// If the given `storage_root` is `None`, `self.root` will be used. /// If the given `storage_root` is `None`, `self.root` will be used.
#[cfg(feature = "std")]
#[inline] #[inline]
fn with_recorder_and_cache<R>( fn with_recorder_and_cache<R>(
&self, &self,
@@ -304,32 +301,23 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> TrieBackendEss
) -> R, ) -> R,
) -> R { ) -> R {
let storage_root = storage_root.unwrap_or_else(|| self.root); let storage_root = storage_root.unwrap_or_else(|| self.root);
let mut recorder = self.recorder.as_ref().map(|r| r.as_trie_recorder(storage_root)); let mut cache = self.trie_node_cache.as_ref().map(|c| c.as_trie_db_cache(storage_root));
let recorder = match recorder.as_mut() {
Some(recorder) => Some(recorder as &mut dyn TrieRecorder<H::Out>),
None => None,
};
let mut cache = self
.trie_node_cache
.as_ref()
.map(|c| c.as_local_trie_cache().as_trie_db_cache(storage_root));
let cache = cache.as_mut().map(|c| c as _); let cache = cache.as_mut().map(|c| c as _);
callback(recorder, cache) #[cfg(feature = "std")]
} {
let mut recorder = self.recorder.as_ref().map(|r| r.as_trie_recorder(storage_root));
let recorder = match recorder.as_mut() {
Some(recorder) => Some(recorder as &mut dyn TrieRecorder<H::Out>),
None => None,
};
callback(recorder, cache)
}
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
#[inline] {
fn with_recorder_and_cache<R>( callback(None, cache)
&self, }
_: Option<H::Out>,
callback: impl FnOnce(
Option<&mut dyn TrieRecorder<H::Out>>,
Option<&mut dyn TrieCache<NodeCodec<H>>>,
) -> R,
) -> R {
callback(None, None)
} }
/// Call the given closure passing it the recorder and the cache. /// Call the given closure passing it the recorder and the cache.
@@ -356,12 +344,12 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> TrieBackendEss
}; };
let result = if let Some(local_cache) = self.trie_node_cache.as_ref() { let result = if let Some(local_cache) = self.trie_node_cache.as_ref() {
let mut cache = local_cache.as_local_trie_cache().as_trie_db_mut_cache(); let mut cache = local_cache.as_trie_db_mut_cache();
let (new_root, r) = callback(recorder, Some(&mut cache)); let (new_root, r) = callback(recorder, Some(&mut cache));
if let Some(new_root) = new_root { if let Some(new_root) = new_root {
cache.merge_into(local_cache.as_local_trie_cache(), new_root); local_cache.merge(cache, new_root);
} }
r r
@@ -375,17 +363,29 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> TrieBackendEss
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
fn with_recorder_and_cache_for_storage_root<R>( fn with_recorder_and_cache_for_storage_root<R>(
&self, &self,
_: Option<H::Out>, _storage_root: Option<H::Out>,
callback: impl FnOnce( callback: impl FnOnce(
Option<&mut dyn TrieRecorder<H::Out>>, Option<&mut dyn TrieRecorder<H::Out>>,
Option<&mut dyn TrieCache<NodeCodec<H>>>, Option<&mut dyn TrieCache<NodeCodec<H>>>,
) -> (Option<H::Out>, R), ) -> (Option<H::Out>, R),
) -> R { ) -> R {
callback(None, None).1 if let Some(local_cache) = self.trie_node_cache.as_ref() {
let mut cache = local_cache.as_trie_db_mut_cache();
let (new_root, r) = callback(None, Some(&mut cache));
if let Some(new_root) = new_root {
local_cache.merge(cache, new_root);
}
r
} else {
callback(None, None).1
}
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
TrieBackendEssence<S, H, C> TrieBackendEssence<S, H, C>
where where
H::Out: Codec + Ord, H::Out: Codec + Ord,
@@ -805,8 +805,8 @@ where
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> AsHashDB<H, DBValue> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
for TrieBackendEssence<S, H, C> AsHashDB<H, DBValue> for TrieBackendEssence<S, H, C>
{ {
fn as_hash_db<'b>(&'b self) -> &'b (dyn HashDB<H, DBValue> + 'b) { fn as_hash_db<'b>(&'b self) -> &'b (dyn HashDB<H, DBValue> + 'b) {
self self
@@ -816,7 +816,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync>
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> HashDB<H, DBValue> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync> HashDB<H, DBValue>
for TrieBackendEssence<S, H, C> for TrieBackendEssence<S, H, C>
{ {
fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> { fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
@@ -849,7 +849,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync>
} }
} }
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
HashDBRef<H, DBValue> for TrieBackendEssence<S, H, C> HashDBRef<H, DBValue> for TrieBackendEssence<S, H, C>
{ {
fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> { fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
+1 -1
View File
@@ -529,7 +529,7 @@ impl<'a, H: Hasher> TrieCache<'a, H> {
/// `storage_root` is the new storage root that was obtained after finishing all operations /// `storage_root` is the new storage root that was obtained after finishing all operations
/// using the [`TrieDBMut`](trie_db::TrieDBMut). /// using the [`TrieDBMut`](trie_db::TrieDBMut).
pub fn merge_into(self, local: &LocalTrieCache<H>, storage_root: H::Out) { pub fn merge_into(self, local: &LocalTrieCache<H>, storage_root: H::Out) {
let cache = if let ValueCache::Fresh(cache) = self.value_cache { cache } else { return }; let ValueCache::Fresh(cache) = self.value_cache else { return };
if !cache.is_empty() { if !cache.is_empty() {
let mut value_cache = local.value_cache.lock(); let mut value_cache = local.value_cache.lock();