mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 19:47:59 +00:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user