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
+32 -63
View File
@@ -125,13 +125,13 @@ impl sp_std::fmt::Display for DefaultError {
}
pub use crate::{
backend::{Backend, IterArgs, KeysIter, PairsIter, StorageIterator},
backend::{Backend, BackendTransaction, IterArgs, KeysIter, PairsIter, StorageIterator},
error::{Error, ExecutionError},
ext::Ext,
overlayed_changes::{
ChildStorageCollection, IndexOperation, OffchainChangesCollection,
OffchainOverlayedChanges, OverlayedChanges, StorageChanges, StorageCollection, StorageKey,
StorageTransactionCache, StorageValue,
StorageValue,
},
stats::{StateMachineStats, UsageInfo, UsageUnit},
trie_backend::{TrieBackend, TrieBackendBuilder},
@@ -143,7 +143,7 @@ mod std_reexport {
pub use crate::{
basic::BasicExternalities,
error::{Error, ExecutionError},
in_memory_backend::{new_in_mem, new_in_mem_hash_key},
in_memory_backend::new_in_mem,
read_only::{InspectState, ReadOnlyExternalities},
testing::TestExternalities,
trie_backend::create_proof_check_backend,
@@ -168,6 +168,7 @@ mod execution {
traits::{CallContext, CodeExecutor, RuntimeCode},
};
use sp_externalities::Extensions;
use sp_trie::PrefixedMemoryDB;
use std::collections::{HashMap, HashSet};
pub(crate) type CallResult<E> = Result<Vec<u8>, E>;
@@ -176,7 +177,7 @@ mod execution {
pub type DefaultHandler<E> = fn(CallResult<E>, CallResult<E>) -> CallResult<E>;
/// Trie backend with in-memory storage.
pub type InMemoryBackend<H> = TrieBackend<MemoryDB<H>, H>;
pub type InMemoryBackend<H> = TrieBackend<PrefixedMemoryDB<H>, H>;
/// Storage backend trust level.
#[derive(Debug, Clone)]
@@ -199,9 +200,8 @@ mod execution {
exec: &'a Exec,
method: &'a str,
call_data: &'a [u8],
overlay: &'a mut OverlayedChanges,
overlay: &'a mut OverlayedChanges<H>,
extensions: &'a mut Extensions,
storage_transaction_cache: Option<&'a mut StorageTransactionCache<B::Transaction, H>>,
runtime_code: &'a RuntimeCode<'a>,
stats: StateMachineStats,
/// The hash of the block the state machine will be executed on.
@@ -231,7 +231,7 @@ mod execution {
/// Creates new substrate state machine.
pub fn new(
backend: &'a B,
overlay: &'a mut OverlayedChanges,
overlay: &'a mut OverlayedChanges<H>,
exec: &'a Exec,
method: &'a str,
call_data: &'a [u8],
@@ -246,7 +246,6 @@ mod execution {
call_data,
extensions,
overlay,
storage_transaction_cache: None,
runtime_code,
stats: StateMachineStats::default(),
parent_hash: None,
@@ -254,19 +253,6 @@ mod execution {
}
}
/// Use given `cache` as storage transaction cache.
///
/// The cache will be used to cache storage transactions that can be build while executing a
/// function in the runtime. For example, when calculating the storage root a transaction is
/// build that will be cached.
pub fn with_storage_transaction_cache(
mut self,
cache: Option<&'a mut StorageTransactionCache<B::Transaction, H>>,
) -> Self {
self.storage_transaction_cache = cache;
self
}
/// Set the given `parent_hash` as the hash of the parent block.
///
/// This will be used for improved logging.
@@ -284,18 +270,11 @@ mod execution {
///
/// Returns the SCALE encoded result of the executed function.
pub fn execute(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
let mut cache = StorageTransactionCache::default();
let cache = match self.storage_transaction_cache.as_mut() {
Some(cache) => cache,
None => &mut cache,
};
self.overlay
.enter_runtime()
.expect("StateMachine is never called from the runtime; qed");
let mut ext = Ext::new(self.overlay, cache, self.backend, Some(self.extensions));
let mut ext = Ext::new(self.overlay, self.backend, Some(self.extensions));
let ext_id = ext.id;
@@ -331,7 +310,7 @@ mod execution {
/// Prove execution using the given state backend, overlayed changes, and call executor.
pub fn prove_execution<B, H, Exec>(
backend: &mut B,
overlay: &mut OverlayedChanges,
overlay: &mut OverlayedChanges<H>,
exec: &Exec,
method: &str,
call_data: &[u8],
@@ -366,7 +345,7 @@ mod execution {
/// blocks (e.g. a transaction at a time), ensure a different method is used.
pub fn prove_execution_on_trie_backend<S, H, Exec>(
trie_backend: &TrieBackend<S, H>,
overlay: &mut OverlayedChanges,
overlay: &mut OverlayedChanges<H>,
exec: &Exec,
method: &str,
call_data: &[u8],
@@ -405,7 +384,7 @@ mod execution {
pub fn execution_proof_check<H, Exec>(
root: H::Out,
proof: StorageProof,
overlay: &mut OverlayedChanges,
overlay: &mut OverlayedChanges<H>,
exec: &Exec,
method: &str,
call_data: &[u8],
@@ -430,7 +409,7 @@ mod execution {
/// Check execution proof on proving backend, generated by `prove_execution` call.
pub fn execution_proof_check_on_trie_backend<H, Exec>(
trie_backend: &TrieBackend<MemoryDB<H>, H>,
overlay: &mut OverlayedChanges,
overlay: &mut OverlayedChanges<H>,
exec: &Exec,
method: &str,
call_data: &[u8],
@@ -1109,7 +1088,7 @@ mod execution {
#[cfg(test)]
mod tests {
use super::{backend::AsTrieBackend, ext::Ext, *};
use crate::{execution::CallResult, in_memory_backend::new_in_mem_hash_key};
use crate::{execution::CallResult, in_memory_backend::new_in_mem};
use assert_matches::assert_matches;
use codec::Encode;
use sp_core::{
@@ -1287,8 +1266,7 @@ mod tests {
let overlay_limit = overlay.clone();
{
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
let _ = ext.clear_prefix(b"ab", None, None);
}
overlay.commit_transaction().unwrap();
@@ -1311,8 +1289,7 @@ mod tests {
let mut overlay = overlay_limit;
{
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
assert_matches!(
ext.clear_prefix(b"ab", Some(1), None).deconstruct(),
(Some(_), 1, 3, 1)
@@ -1356,8 +1333,7 @@ mod tests {
overlay.set_child_storage(&child_info, b"4".to_vec(), Some(b"1312".to_vec()));
{
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None);
let mut ext = Ext::new(&mut overlay, &backend, None);
let r = ext.kill_child_storage(&child_info, Some(2), None);
assert_matches!(r.deconstruct(), (Some(_), 2, 6, 2));
}
@@ -1392,8 +1368,7 @@ mod tests {
];
let backend = InMemoryBackend::<BlakeTwo256>::from((initial, StateVersion::default()));
let mut overlay = OverlayedChanges::default();
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None);
let mut ext = Ext::new(&mut overlay, &backend, None);
let r = ext.kill_child_storage(&child_info, Some(0), None).deconstruct();
assert_matches!(r, (Some(_), 0, 0, 0));
let r = ext
@@ -1422,8 +1397,7 @@ mod tests {
];
let backend = InMemoryBackend::<BlakeTwo256>::from((initial, StateVersion::default()));
let mut overlay = OverlayedChanges::default();
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None);
let mut ext = Ext::new(&mut overlay, &backend, None);
assert_eq!(ext.kill_child_storage(&child_info, None, None).deconstruct(), (None, 4, 4, 4));
}
@@ -1431,11 +1405,10 @@ mod tests {
fn set_child_storage_works() {
let child_info = ChildInfo::new_default(b"sub1");
let child_info = &child_info;
let state = new_in_mem_hash_key::<BlakeTwo256>();
let state = new_in_mem::<BlakeTwo256>();
let backend = state.as_trie_backend();
let mut overlay = OverlayedChanges::default();
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
ext.set_child_storage(child_info, b"abc".to_vec(), b"def".to_vec());
assert_eq!(ext.child_storage(child_info, b"abc"), Some(b"def".to_vec()));
@@ -1447,19 +1420,18 @@ mod tests {
fn append_storage_works() {
let reference_data = vec![b"data1".to_vec(), b"2".to_vec(), b"D3".to_vec(), b"d4".to_vec()];
let key = b"key".to_vec();
let state = new_in_mem_hash_key::<BlakeTwo256>();
let state = new_in_mem::<BlakeTwo256>();
let backend = state.as_trie_backend();
let mut overlay = OverlayedChanges::default();
let mut cache = StorageTransactionCache::default();
{
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
ext.storage_append(key.clone(), reference_data[0].encode());
assert_eq!(ext.storage(key.as_slice()), Some(vec![reference_data[0].clone()].encode()));
}
overlay.start_transaction();
{
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
for i in reference_data.iter().skip(1) {
ext.storage_append(key.clone(), i.encode());
@@ -1468,7 +1440,7 @@ mod tests {
}
overlay.rollback_transaction().unwrap();
{
let ext = Ext::new(&mut overlay, &mut cache, backend, None);
let ext = Ext::new(&mut overlay, backend, None);
assert_eq!(ext.storage(key.as_slice()), Some(vec![reference_data[0].clone()].encode()));
}
}
@@ -1483,14 +1455,13 @@ mod tests {
}
let key = b"events".to_vec();
let mut cache = StorageTransactionCache::default();
let state = new_in_mem_hash_key::<BlakeTwo256>();
let state = new_in_mem::<BlakeTwo256>();
let backend = state.as_trie_backend();
let mut overlay = OverlayedChanges::default();
// For example, block initialization with event.
{
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
ext.clear_storage(key.as_slice());
ext.storage_append(key.clone(), Item::InitializationItem.encode());
}
@@ -1498,7 +1469,7 @@ mod tests {
// For example, first transaction resulted in panic during block building
{
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
assert_eq!(ext.storage(key.as_slice()), Some(vec![Item::InitializationItem].encode()));
@@ -1513,7 +1484,7 @@ mod tests {
// Then we apply next transaction which is valid this time.
{
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
assert_eq!(ext.storage(key.as_slice()), Some(vec![Item::InitializationItem].encode()));
@@ -1528,7 +1499,7 @@ mod tests {
// Then only initlaization item and second (committed) item should persist.
{
let ext = Ext::new(&mut overlay, &mut cache, backend, None);
let ext = Ext::new(&mut overlay, backend, None);
assert_eq!(
ext.storage(key.as_slice()),
Some(vec![Item::InitializationItem, Item::CommitedItem].encode()),
@@ -1945,12 +1916,11 @@ mod tests {
let mut transaction = {
let backend = test_trie(state_version, None, None);
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None);
let mut ext = Ext::new(&mut overlay, &backend, None);
ext.set_child_storage(&child_info_1, b"abc".to_vec(), b"def".to_vec());
ext.set_child_storage(&child_info_2, b"abc".to_vec(), b"def".to_vec());
ext.storage_root(state_version);
cache.transaction.unwrap()
overlay.drain_storage_changes(&backend, state_version).unwrap().transaction
};
let mut duplicate = false;
for (k, (value, rc)) in transaction.drain().iter() {
@@ -1982,8 +1952,7 @@ mod tests {
assert_eq!(overlay.storage(b"bbb"), None);
{
let mut cache = StorageTransactionCache::default();
let mut ext = Ext::new(&mut overlay, &mut cache, backend, None);
let mut ext = Ext::new(&mut overlay, backend, None);
assert_eq!(ext.storage(b"bbb"), Some(vec![]));
assert_eq!(ext.storage(b"ccc"), Some(vec![]));
ext.clear_storage(b"ccc");