Set StateBackend::Transaction to PrefixedMemoryDB (#14612)

* Yep

* Try to get it working everywhere

* Make `from_raw_storage` start with an empty db

* More fixes!

* Make everything compile

* Fix `child_storage_root`

* Fix after merge

* Cleanups

* Update primitives/state-machine/src/overlayed_changes/mod.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Review comments

* Fix issues

* Silence warning

* FMT

* Clippy

---------

Co-authored-by: Davide Galassi <davxy@datawok.net>
This commit is contained in:
Bastian Köcher
2023-08-17 12:49:38 +02:00
committed by GitHub
parent a892fa7f92
commit ecf8035da6
67 changed files with 750 additions and 1150 deletions
+33 -129
View File
@@ -22,7 +22,7 @@ use crate::overlayed_changes::OverlayedExtensions;
use crate::{
backend::Backend, IndexOperation, IterArgs, OverlayedChanges, StorageKey, StorageValue,
};
use codec::{Decode, Encode, EncodeAppend};
use codec::{Encode, EncodeAppend};
use hash_db::Hasher;
#[cfg(feature = "std")]
use sp_core::hexdisplay::HexDisplay;
@@ -30,9 +30,8 @@ use sp_core::storage::{
well_known_keys::is_child_storage_key, ChildInfo, StateVersion, TrackedStorageKey,
};
use sp_externalities::{Extension, ExtensionStore, Externalities, MultiRemovalResults};
use sp_trie::{empty_child_trie_root, LayoutV1};
use crate::{log_error, trace, warn, StorageTransactionCache};
use crate::{log_error, trace, warn};
use sp_std::{
any::{Any, TypeId},
boxed::Box,
@@ -98,11 +97,9 @@ where
B: 'a + Backend<H>,
{
/// The overlayed changes to write to.
overlay: &'a mut OverlayedChanges,
overlay: &'a mut OverlayedChanges<H>,
/// The storage backend to read from.
backend: &'a B,
/// The cache for the storage transactions.
storage_transaction_cache: &'a mut StorageTransactionCache<B::Transaction, H>,
/// Pseudo-unique id used for tracing.
pub id: u16,
/// Extensions registered with this instance.
@@ -117,37 +114,24 @@ where
{
/// Create a new `Ext`.
#[cfg(not(feature = "std"))]
pub fn new(
overlay: &'a mut OverlayedChanges,
storage_transaction_cache: &'a mut StorageTransactionCache<B::Transaction, H>,
backend: &'a B,
) -> Self {
Ext { overlay, backend, id: 0, storage_transaction_cache }
pub fn new(overlay: &'a mut OverlayedChanges<H>, backend: &'a B) -> Self {
Ext { overlay, backend, id: 0 }
}
/// Create a new `Ext` from overlayed changes and read-only backend
#[cfg(feature = "std")]
pub fn new(
overlay: &'a mut OverlayedChanges,
storage_transaction_cache: &'a mut StorageTransactionCache<B::Transaction, H>,
overlay: &'a mut OverlayedChanges<H>,
backend: &'a B,
extensions: Option<&'a mut sp_externalities::Extensions>,
) -> Self {
Self {
overlay,
backend,
storage_transaction_cache,
id: rand::random(),
extensions: extensions.map(OverlayedExtensions::new),
}
}
/// Invalidates the currently cached storage root and the db transaction.
///
/// Called when there are changes that likely will invalidate the storage root.
fn mark_dirty(&mut self) {
self.storage_transaction_cache.reset();
}
}
#[cfg(test)]
@@ -412,7 +396,6 @@ where
),
);
self.mark_dirty();
self.overlay.set_storage(key, value);
}
@@ -432,7 +415,6 @@ where
);
let _guard = guard();
self.mark_dirty();
self.overlay.set_child_storage(child_info, key, value);
}
@@ -449,7 +431,6 @@ where
child_info = %HexDisplay::from(&child_info.storage_key()),
);
let _guard = guard();
self.mark_dirty();
let overlay = self.overlay.clear_child_storage(child_info);
let (maybe_cursor, backend, loops) =
self.limit_remove_from_backend(Some(child_info), None, maybe_limit, maybe_cursor);
@@ -478,7 +459,6 @@ where
return MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 }
}
self.mark_dirty();
let overlay = self.overlay.clear_prefix(prefix);
let (maybe_cursor, backend, loops) =
self.limit_remove_from_backend(None, Some(prefix), maybe_limit, maybe_cursor);
@@ -501,7 +481,6 @@ where
);
let _guard = guard();
self.mark_dirty();
let overlay = self.overlay.clear_child_prefix(child_info, prefix);
let (maybe_cursor, backend, loops) = self.limit_remove_from_backend(
Some(child_info),
@@ -522,7 +501,6 @@ where
);
let _guard = guard();
self.mark_dirty();
let backend = &mut self.backend;
let current_value = self.overlay.value_mut_or_insert_with(&key, || {
@@ -533,27 +511,17 @@ where
fn storage_root(&mut self, state_version: StateVersion) -> Vec<u8> {
let _guard = guard();
if let Some(ref root) = self.storage_transaction_cache.transaction_storage_root {
trace!(
target: "state",
method = "StorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = true,
);
return root.encode()
}
let root =
self.overlay
.storage_root(self.backend, self.storage_transaction_cache, state_version);
let (root, _cached) = self.overlay.storage_root(self.backend, state_version);
trace!(
target: "state",
method = "StorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = false,
cached = %_cached,
);
root.encode()
}
@@ -563,74 +531,22 @@ where
state_version: StateVersion,
) -> Vec<u8> {
let _guard = guard();
let storage_key = child_info.storage_key();
let prefixed_storage_key = child_info.prefixed_storage_key();
if self.storage_transaction_cache.transaction_storage_root.is_some() {
let root = self
.storage(prefixed_storage_key.as_slice())
.and_then(|k| Decode::decode(&mut &k[..]).ok())
// V1 is equivalent to V0 on empty root.
.unwrap_or_else(empty_child_trie_root::<LayoutV1<H>>);
trace!(
target: "state",
method = "ChildStorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
child_info = %HexDisplay::from(&storage_key),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = true,
);
root.encode()
} else {
let root = if let Some((changes, info)) = self.overlay.child_changes(storage_key) {
let delta = changes.map(|(k, v)| (k.as_ref(), v.value().map(AsRef::as_ref)));
Some(self.backend.child_storage_root(info, delta, state_version))
} else {
None
};
if let Some((root, is_empty, _)) = root {
let root = root.encode();
// We store update in the overlay in order to be able to use
// 'self.storage_transaction' cache. This is brittle as it rely on Ext only querying
// the trie backend for storage root.
// A better design would be to manage 'child_storage_transaction' in a
// similar way as 'storage_transaction' but for each child trie.
if is_empty {
self.overlay.set_storage(prefixed_storage_key.into_inner(), None);
} else {
self.overlay.set_storage(prefixed_storage_key.into_inner(), Some(root.clone()));
}
let (root, _cached) = self
.overlay
.child_storage_root(child_info, self.backend, state_version)
.expect(EXT_NOT_ALLOWED_TO_FAIL);
trace!(
target: "state",
method = "ChildStorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
child_info = %HexDisplay::from(&storage_key),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = false,
);
trace!(
target: "state",
method = "ChildStorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
child_info = %HexDisplay::from(&child_info.storage_key()),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = %_cached,
);
root
} else {
// empty overlay
let root = self
.storage(prefixed_storage_key.as_slice())
.and_then(|k| Decode::decode(&mut &k[..]).ok())
// V1 is equivalent to V0 on empty root.
.unwrap_or_else(empty_child_trie_root::<LayoutV1<H>>);
trace!(
target: "state",
method = "ChildStorageRoot",
ext_id = %HexDisplay::from(&self.id.to_le_bytes()),
child_info = %HexDisplay::from(&storage_key),
storage_root = %HexDisplay::from(&root.as_ref()),
cached = false,
);
root.encode()
}
}
root.encode()
}
fn storage_index_transaction(&mut self, index: u32, hash: &[u8], size: u32) {
@@ -669,7 +585,6 @@ where
}
fn storage_rollback_transaction(&mut self) -> Result<(), ()> {
self.mark_dirty();
self.overlay.rollback_transaction().map_err(|_| ())
}
@@ -682,14 +597,9 @@ where
self.overlay.rollback_transaction().expect(BENCHMARKING_FN);
}
self.overlay
.drain_storage_changes(
self.backend,
self.storage_transaction_cache,
Default::default(), // using any state
)
.drain_storage_changes(self.backend, Default::default())
.expect(EXT_NOT_ALLOWED_TO_FAIL);
self.backend.wipe().expect(EXT_NOT_ALLOWED_TO_FAIL);
self.mark_dirty();
self.overlay
.enter_runtime()
.expect("We have reset the overlay above, so we can not be in the runtime; qed");
@@ -703,7 +613,7 @@ where
}
let changes = self
.overlay
.drain_storage_changes(self.backend, self.storage_transaction_cache, state_version)
.drain_storage_changes(self.backend, state_version)
.expect(EXT_NOT_ALLOWED_TO_FAIL);
self.backend
.commit(
@@ -713,7 +623,6 @@ where
changes.child_storage_changes,
)
.expect(EXT_NOT_ALLOWED_TO_FAIL);
self.mark_dirty();
self.overlay
.enter_runtime()
.expect("We have reset the overlay above, so we can not be in the runtime; qed");
@@ -914,7 +823,7 @@ where
mod tests {
use super::*;
use crate::InMemoryBackend;
use codec::Encode;
use codec::{Decode, Encode};
use sp_core::{
map,
storage::{Storage, StorageChild},
@@ -926,7 +835,6 @@ mod tests {
#[test]
fn next_storage_key_works() {
let mut cache = StorageTransactionCache::default();
let mut overlay = OverlayedChanges::default();
overlay.set_storage(vec![20], None);
overlay.set_storage(vec![30], Some(vec![31]));
@@ -943,7 +851,7 @@ mod tests {
)
.into();
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
// next_backend < next_overlay
assert_eq!(ext.next_storage_key(&[5]), Some(vec![10]));
@@ -959,7 +867,7 @@ mod tests {
drop(ext);
overlay.set_storage(vec![50], Some(vec![50]));
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
// next_overlay exist but next_backend doesn't exist
assert_eq!(ext.next_storage_key(&[40]), Some(vec![50]));
@@ -967,7 +875,6 @@ mod tests {
#[test]
fn next_storage_key_works_with_a_lot_empty_values_in_overlay() {
let mut cache = StorageTransactionCache::default();
let mut overlay = OverlayedChanges::default();
overlay.set_storage(vec![20], None);
overlay.set_storage(vec![21], None);
@@ -990,7 +897,7 @@ mod tests {
)
.into();
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
assert_eq!(ext.next_storage_key(&[5]), Some(vec![30]));
@@ -1002,7 +909,6 @@ mod tests {
let child_info = ChildInfo::new_default(b"Child1");
let child_info = &child_info;
let mut cache = StorageTransactionCache::default();
let mut overlay = OverlayedChanges::default();
overlay.set_child_storage(child_info, vec![20], None);
overlay.set_child_storage(child_info, vec![30], Some(vec![31]));
@@ -1024,7 +930,7 @@ mod tests {
)
.into();
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
// next_backend < next_overlay
assert_eq!(ext.next_child_storage_key(child_info, &[5]), Some(vec![10]));
@@ -1040,7 +946,7 @@ mod tests {
drop(ext);
overlay.set_child_storage(child_info, vec![50], Some(vec![50]));
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
// next_overlay exist but next_backend doesn't exist
assert_eq!(ext.next_child_storage_key(child_info, &[40]), Some(vec![50]));
@@ -1050,7 +956,6 @@ mod tests {
fn child_storage_works() {
let child_info = ChildInfo::new_default(b"Child1");
let child_info = &child_info;
let mut cache = StorageTransactionCache::default();
let mut overlay = OverlayedChanges::default();
overlay.set_child_storage(child_info, vec![20], None);
overlay.set_child_storage(child_info, vec![30], Some(vec![31]));
@@ -1072,7 +977,7 @@ mod tests {
)
.into();
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
assert_eq!(ext.child_storage(child_info, &[10]), Some(vec![10]));
assert_eq!(
@@ -1094,7 +999,6 @@ mod tests {
fn clear_prefix_cannot_delete_a_child_root() {
let child_info = ChildInfo::new_default(b"Child1");
let child_info = &child_info;
let mut cache = StorageTransactionCache::default();
let mut overlay = OverlayedChanges::default();
let backend = (
Storage {
@@ -1112,7 +1016,7 @@ mod tests {
)
.into();
let ext = TestExt::new(&mut overlay, &mut cache, &backend, None);
let ext = TestExt::new(&mut overlay, &backend, None);
use sp_core::storage::well_known_keys;
let mut ext = ext;