mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 07:27:55 +00:00
Code redundancy between ext implementation and testing. (#3830)
* fix child_storage_hash * extract common implementation for ext and testing * cleaning impl. * replace ExtBasisMut by actual Ext * remove extbasis. * Update tests to use Ext from test externalities. * use Ext constructor for getting ext from TestExternalities. * Add missing extensions from ext. * fix wasmi test * Fix merge error.
This commit is contained in:
@@ -21,22 +21,20 @@ use hash_db::Hasher;
|
||||
use crate::{
|
||||
backend::{InMemory, Backend}, OverlayedChanges,
|
||||
changes_trie::{
|
||||
build_changes_trie, InMemoryStorage as ChangesTrieInMemoryStorage,
|
||||
InMemoryStorage as ChangesTrieInMemoryStorage,
|
||||
BlockNumber as ChangesTrieBlockNumber,
|
||||
},
|
||||
ext::Ext,
|
||||
};
|
||||
use primitives::{
|
||||
storage::{
|
||||
ChildStorageKey,
|
||||
well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key}
|
||||
},
|
||||
traits::Externalities, hash::H256, Blake2Hasher,
|
||||
hash::H256, Blake2Hasher,
|
||||
};
|
||||
use codec::Encode;
|
||||
use externalities::{Extensions, Extension};
|
||||
|
||||
const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime";
|
||||
|
||||
type StorageTuple = (HashMap<Vec<u8>, Vec<u8>>, HashMap<Vec<u8>, HashMap<Vec<u8>, Vec<u8>>>);
|
||||
|
||||
/// Simple HashMap-based Externalities impl.
|
||||
@@ -48,6 +46,17 @@ pub struct TestExternalities<H: Hasher<Out=H256>=Blake2Hasher, N: ChangesTrieBlo
|
||||
}
|
||||
|
||||
impl<H: Hasher<Out=H256>, N: ChangesTrieBlockNumber> TestExternalities<H, N> {
|
||||
|
||||
/// Get externalities implementation.
|
||||
pub fn ext(&mut self) -> Ext<H, N, InMemory<H>, ChangesTrieInMemoryStorage<H, N>> {
|
||||
Ext::new(
|
||||
&mut self.overlay,
|
||||
&self.backend,
|
||||
Some(&self.changes_trie_storage),
|
||||
Some(&mut self.extensions),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new instance of `TestExternalities` with storage.
|
||||
pub fn new(storage: StorageTuple) -> Self {
|
||||
Self::new_with_code(&[], storage)
|
||||
@@ -118,7 +127,8 @@ impl<H: Hasher<Out=H256>, N: ChangesTrieBlockNumber> TestExternalities<H, N> {
|
||||
///
|
||||
/// Returns the result of the given closure.
|
||||
pub fn execute_with<R>(&mut self, execute: impl FnOnce() -> R) -> R {
|
||||
externalities::set_and_run_with_externalities(self, execute)
|
||||
let mut ext = self.ext();
|
||||
externalities::set_and_run_with_externalities(&mut ext, execute)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,156 +156,6 @@ impl<H: Hasher<Out=H256>, N: ChangesTrieBlockNumber> From<StorageTuple> for Test
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, N> Externalities for TestExternalities<H, N> where
|
||||
H: Hasher<Out=H256>,
|
||||
N: ChangesTrieBlockNumber,
|
||||
{
|
||||
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||
|
||||
self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL))
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
self.storage(key).map(|v| H::hash(&v))
|
||||
}
|
||||
|
||||
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)
|
||||
}
|
||||
|
||||
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
self.storage_hash(key)
|
||||
}
|
||||
|
||||
fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.overlay
|
||||
.child_storage(storage_key.as_ref(), key)
|
||||
.map(|x| x.map(|x| x.to_vec()))
|
||||
.unwrap_or_else(|| self.backend
|
||||
.child_storage(storage_key.as_ref(), key)
|
||||
.expect(EXT_NOT_ALLOWED_TO_FAIL)
|
||||
)
|
||||
}
|
||||
|
||||
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
self.child_storage(storage_key, key).map(|v| H::hash(&v))
|
||||
}
|
||||
|
||||
fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.backend
|
||||
.child_storage(storage_key.as_ref(), key)
|
||||
.map(|x| x.map(|x| x.to_vec()))
|
||||
.expect(EXT_NOT_ALLOWED_TO_FAIL)
|
||||
}
|
||||
|
||||
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
self.child_storage_hash(storage_key, key)
|
||||
}
|
||||
|
||||
fn place_storage(&mut self, key: Vec<u8>, maybe_value: Option<Vec<u8>>) {
|
||||
if is_child_storage_key(&key) {
|
||||
panic!("Refuse to directly set child storage key");
|
||||
}
|
||||
|
||||
self.overlay.set_storage(key, maybe_value);
|
||||
}
|
||||
|
||||
fn place_child_storage(
|
||||
&mut self,
|
||||
storage_key: ChildStorageKey,
|
||||
key: Vec<u8>,
|
||||
value: Option<Vec<u8>>,
|
||||
) {
|
||||
self.overlay.set_child_storage(storage_key.into_owned(), key, value);
|
||||
}
|
||||
|
||||
fn kill_child_storage(&mut self, storage_key: ChildStorageKey) {
|
||||
let backend = &self.backend;
|
||||
let overlay = &mut self.overlay;
|
||||
|
||||
overlay.clear_child_storage(storage_key.as_ref());
|
||||
backend.for_keys_in_child_storage(storage_key.as_ref(), |key| {
|
||||
overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None);
|
||||
});
|
||||
}
|
||||
|
||||
fn clear_prefix(&mut self, prefix: &[u8]) {
|
||||
if is_child_storage_key(prefix) {
|
||||
panic!("Refuse to directly clear prefix that is part of child storage key");
|
||||
}
|
||||
|
||||
self.overlay.clear_prefix(prefix);
|
||||
|
||||
let backend = &self.backend;
|
||||
let overlay = &mut self.overlay;
|
||||
backend.for_keys_with_prefix(prefix, |key| {
|
||||
overlay.set_storage(key.to_vec(), None);
|
||||
});
|
||||
}
|
||||
|
||||
fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) {
|
||||
self.overlay.clear_child_prefix(storage_key.as_ref(), prefix);
|
||||
|
||||
let backend = &self.backend;
|
||||
let overlay = &mut self.overlay;
|
||||
backend.for_child_keys_with_prefix(storage_key.as_ref(), prefix, |key| {
|
||||
overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None);
|
||||
});
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 { 42 }
|
||||
|
||||
fn storage_root(&mut self) -> H256 {
|
||||
let child_storage_keys =
|
||||
self.overlay.prospective.children.keys()
|
||||
.chain(self.overlay.committed.children.keys());
|
||||
|
||||
let child_delta_iter = child_storage_keys.map(|storage_key|
|
||||
(storage_key.clone(), self.overlay.committed.children.get(storage_key)
|
||||
.into_iter()
|
||||
.flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone())))
|
||||
.chain(self.overlay.prospective.children.get(storage_key)
|
||||
.into_iter()
|
||||
.flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone()))))));
|
||||
|
||||
|
||||
// compute and memoize
|
||||
let delta = self.overlay.committed.top.iter().map(|(k, v)| (k.clone(), v.value.clone()))
|
||||
.chain(self.overlay.prospective.top.iter().map(|(k, v)| (k.clone(), v.value.clone())));
|
||||
self.backend.full_storage_root(delta, child_delta_iter).0
|
||||
}
|
||||
|
||||
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
|
||||
let storage_key = storage_key.as_ref();
|
||||
|
||||
let (root, is_empty, _) = {
|
||||
let delta = self.overlay.committed.children.get(storage_key)
|
||||
.into_iter()
|
||||
.flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value)))
|
||||
.chain(self.overlay.prospective.children.get(storage_key)
|
||||
.into_iter()
|
||||
.flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value))));
|
||||
|
||||
self.backend.child_storage_root(storage_key, delta)
|
||||
};
|
||||
if is_empty {
|
||||
self.overlay.set_storage(storage_key.into(), None);
|
||||
} else {
|
||||
self.overlay.set_storage(storage_key.into(), Some(root.clone()));
|
||||
}
|
||||
root
|
||||
}
|
||||
|
||||
fn storage_changes_root(&mut self, parent: H256) -> Result<Option<H256>, ()> {
|
||||
Ok(build_changes_trie::<_, _, H, N>(
|
||||
&self.backend,
|
||||
Some(&self.changes_trie_storage),
|
||||
&self.overlay,
|
||||
parent,
|
||||
)?.map(|(_, root, _)| root))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, N> externalities::ExtensionStore for TestExternalities<H, N> where
|
||||
H: Hasher<Out=H256>,
|
||||
N: ChangesTrieBlockNumber,
|
||||
@@ -308,12 +168,13 @@ impl<H, N> externalities::ExtensionStore for TestExternalities<H, N> where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use primitives::{Blake2Hasher, H256};
|
||||
use primitives::traits::Externalities;
|
||||
use hex_literal::hex;
|
||||
|
||||
#[test]
|
||||
fn commit_should_work() {
|
||||
let mut ext = TestExternalities::<Blake2Hasher, u64>::default();
|
||||
let mut ext = ext.ext();
|
||||
ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec());
|
||||
ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
|
||||
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
|
||||
@@ -324,6 +185,7 @@ mod tests {
|
||||
#[test]
|
||||
fn set_and_retrieve_code() {
|
||||
let mut ext = TestExternalities::<Blake2Hasher, u64>::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = vec![1, 2, 3];
|
||||
ext.set_storage(CODE.to_vec(), code.clone());
|
||||
|
||||
Reference in New Issue
Block a user