mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
The storage runtime interface should not enforce a hash type (#4231)
* The storage runtime interface should not enforce a hash type Currently the runtime interface enforces `H256` as hash type, but in the future people could use whatever they want as hash type. The hash type always needs to match between the runtime and the node, but that is already required. * Update primitives/externalities/src/lib.rs Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
committed by
Gavin Wood
parent
39388b826b
commit
3e26fceda4
@@ -25,6 +25,7 @@ use trie::{
|
||||
TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration,
|
||||
trie_types::{TrieDBMut, Layout},
|
||||
};
|
||||
use codec::{Encode, Codec};
|
||||
|
||||
/// A state backend is used to read state data and can have changes committed
|
||||
/// to it.
|
||||
@@ -95,7 +96,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
|
||||
/// Calculate the child storage root, with given delta over what is already stored in
|
||||
/// the backend, and produce a "transaction" that can be used to commit. The second argument
|
||||
/// is true if child storage root equals default storage root.
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
|
||||
where
|
||||
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
H::Out: Ord;
|
||||
@@ -134,7 +135,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
|
||||
I1: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
I2i: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
I2: IntoIterator<Item=(Vec<u8>, I2i)>,
|
||||
<H as Hasher>::Out: Ord,
|
||||
H::Out: Ord + Encode,
|
||||
{
|
||||
let mut txs: Self::Transaction = Default::default();
|
||||
let mut child_roots: Vec<_> = Default::default();
|
||||
@@ -146,7 +147,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
|
||||
if empty {
|
||||
child_roots.push((storage_key, None));
|
||||
} else {
|
||||
child_roots.push((storage_key, Some(child_root)));
|
||||
child_roots.push((storage_key, Some(child_root.encode())));
|
||||
}
|
||||
}
|
||||
let (root, parent_txs) = self.storage_root(
|
||||
@@ -190,7 +191,7 @@ impl<'a, T: Backend<H>, H: Hasher> Backend<H> for &'a T {
|
||||
(*self).storage_root(delta)
|
||||
}
|
||||
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
|
||||
where
|
||||
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
H::Out: Ord,
|
||||
@@ -287,7 +288,7 @@ impl<H: Hasher> PartialEq for InMemory<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hasher> InMemory<H> {
|
||||
impl<H: Hasher> InMemory<H> where H::Out: Codec {
|
||||
/// Copy the state, with applied updates
|
||||
pub fn update(&self, changes: <Self as Backend<H>>::Transaction) -> Self {
|
||||
let mut inner: HashMap<_, _> = self.inner.clone();
|
||||
@@ -362,7 +363,7 @@ impl<H: Hasher> InMemory<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hasher> Backend<H> for InMemory<H> {
|
||||
impl<H: Hasher> Backend<H> for InMemory<H> where H::Out: Codec {
|
||||
type Error = Void;
|
||||
type Transaction = Vec<(Option<Vec<u8>>, Vec<u8>, Option<Vec<u8>>)>;
|
||||
type TrieBackendStorage = MemoryDB<H>;
|
||||
@@ -418,7 +419,7 @@ impl<H: Hasher> Backend<H> for InMemory<H> {
|
||||
(root, full_transaction)
|
||||
}
|
||||
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
|
||||
where
|
||||
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
H::Out: Ord
|
||||
|
||||
@@ -26,9 +26,10 @@ use primitives::{
|
||||
well_known_keys::is_child_storage_key, ChildStorageKey, StorageOverlay,
|
||||
ChildrenStorageOverlay
|
||||
},
|
||||
traits::Externalities, Blake2Hasher, hash::H256,
|
||||
traits::Externalities, Blake2Hasher,
|
||||
};
|
||||
use log::warn;
|
||||
use codec::Encode;
|
||||
|
||||
/// Simple HashMap-based Externalities impl.
|
||||
#[derive(Debug)]
|
||||
@@ -118,15 +119,15 @@ impl Externalities for BasicExternalities {
|
||||
self.top.get(key).cloned()
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
self.storage(key).map(|v| Blake2Hasher::hash(&v))
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.storage(key).map(|v| Blake2Hasher::hash(&v).encode())
|
||||
}
|
||||
|
||||
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.storage(key)
|
||||
}
|
||||
|
||||
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
fn original_storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.storage_hash(key)
|
||||
}
|
||||
|
||||
@@ -134,11 +135,15 @@ impl Externalities for BasicExternalities {
|
||||
self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned()
|
||||
}
|
||||
|
||||
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v))
|
||||
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v).encode())
|
||||
}
|
||||
|
||||
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
fn original_child_storage_hash(
|
||||
&self,
|
||||
storage_key: ChildStorageKey,
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
self.child_storage_hash(storage_key, key)
|
||||
}
|
||||
|
||||
@@ -196,7 +201,7 @@ impl Externalities for BasicExternalities {
|
||||
|
||||
fn chain_id(&self) -> u64 { 42 }
|
||||
|
||||
fn storage_root(&mut self) -> H256 {
|
||||
fn storage_root(&mut self) -> Vec<u8> {
|
||||
let mut top = self.top.clone();
|
||||
let keys: Vec<_> = self.children.keys().map(|k| k.to_vec()).collect();
|
||||
// Single child trie implementation currently allows using the same child
|
||||
@@ -215,7 +220,7 @@ impl Externalities for BasicExternalities {
|
||||
}
|
||||
}
|
||||
|
||||
Layout::<Blake2Hasher>::trie_root(self.top.clone())
|
||||
Layout::<Blake2Hasher>::trie_root(self.top.clone()).as_ref().into()
|
||||
}
|
||||
|
||||
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
|
||||
@@ -225,10 +230,10 @@ impl Externalities for BasicExternalities {
|
||||
InMemory::<Blake2Hasher>::default().child_storage_root(storage_key.as_ref(), delta).0
|
||||
} else {
|
||||
default_child_trie_root::<Layout<Blake2Hasher>>(storage_key.as_ref())
|
||||
}
|
||||
}.encode()
|
||||
}
|
||||
|
||||
fn storage_changes_root(&mut self, _parent: H256) -> Result<Option<H256>, ()> {
|
||||
fn storage_changes_root(&mut self, _parent: &[u8]) -> Result<Option<Vec<u8>>, ()> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
@@ -243,7 +248,7 @@ impl externalities::ExtensionStore for BasicExternalities {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use primitives::{H256, map};
|
||||
use primitives::map;
|
||||
use primitives::storage::well_known_keys::CODE;
|
||||
use hex_literal::hex;
|
||||
|
||||
@@ -255,7 +260,7 @@ mod tests {
|
||||
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
|
||||
const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa");
|
||||
|
||||
assert_eq!(ext.storage_root(), H256::from(ROOT));
|
||||
assert_eq!(&ext.storage_root()[..], &ROOT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::collections::btree_map::Entry;
|
||||
use codec::Decode;
|
||||
use codec::{Decode, Encode};
|
||||
use hash_db::Hasher;
|
||||
use num_traits::One;
|
||||
use crate::backend::Backend;
|
||||
@@ -47,6 +47,7 @@ pub(crate) fn prepare_input<'a, B, H, Number>(
|
||||
where
|
||||
B: Backend<H>,
|
||||
H: Hasher + 'a,
|
||||
H::Out: Encode,
|
||||
Number: BlockNumber,
|
||||
{
|
||||
let number = parent.number.clone() + One::one();
|
||||
@@ -200,7 +201,7 @@ fn prepare_digest_input<'a, H, Number>(
|
||||
), String>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: 'a,
|
||||
H::Out: 'a + Encode,
|
||||
Number: BlockNumber,
|
||||
{
|
||||
let build_skewed_digest = config.end.as_ref() == Some(&block);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, Codec};
|
||||
use hash_db::Hasher;
|
||||
use num_traits::Zero;
|
||||
use trie::Recorder;
|
||||
@@ -81,7 +81,7 @@ pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>(
|
||||
max: Number,
|
||||
storage_key: Option<&[u8]>,
|
||||
key: &[u8],
|
||||
) -> Result<Vec<Vec<u8>>, String> {
|
||||
) -> Result<Vec<Vec<u8>>, String> where H::Out: Codec {
|
||||
// we can't query any roots before root
|
||||
let max = ::std::cmp::min(max.clone(), end.number.clone());
|
||||
|
||||
@@ -129,7 +129,7 @@ pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>(
|
||||
max: Number,
|
||||
storage_key: Option<&[u8]>,
|
||||
key: &[u8]
|
||||
) -> Result<Vec<(Number, u32)>, String> {
|
||||
) -> Result<Vec<(Number, u32)>, String> where H::Out: Encode {
|
||||
key_changes_proof_check_with_db(
|
||||
config,
|
||||
roots_storage,
|
||||
@@ -152,7 +152,7 @@ pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>(
|
||||
max: Number,
|
||||
storage_key: Option<&[u8]>,
|
||||
key: &[u8]
|
||||
) -> Result<Vec<(Number, u32)>, String> {
|
||||
) -> Result<Vec<(Number, u32)>, String> where H::Out: Encode {
|
||||
// we can't query any roots before root
|
||||
let max = ::std::cmp::min(max.clone(), end.number.clone());
|
||||
|
||||
@@ -316,8 +316,8 @@ pub struct DrilldownIterator<'a, H, Number>
|
||||
essence: DrilldownIteratorEssence<'a, H, Number>,
|
||||
}
|
||||
|
||||
impl<'a, H: Hasher, Number: BlockNumber> Iterator
|
||||
for DrilldownIterator<'a, H, Number>
|
||||
impl<'a, H: Hasher, Number: BlockNumber> Iterator for DrilldownIterator<'a, H, Number>
|
||||
where H::Out: Encode
|
||||
{
|
||||
type Item = Result<(Number, u32), String>;
|
||||
|
||||
@@ -358,7 +358,7 @@ impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number>
|
||||
where
|
||||
Number: BlockNumber,
|
||||
H: Hasher,
|
||||
H::Out: 'a,
|
||||
H::Out: 'a + Codec,
|
||||
{
|
||||
type Item = Result<(Number, u32), String>;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ pub fn build_changes_trie<'a, B: Backend<H>, S: Storage<H, Number>, H: Hasher, N
|
||||
parent_hash: H::Out,
|
||||
) -> Result<Option<(MemoryDB<H>, H::Out, CacheAction<H::Out, Number>)>, ()>
|
||||
where
|
||||
H::Out: Ord + 'static,
|
||||
H::Out: Ord + 'static + Encode,
|
||||
{
|
||||
let (storage, config) = match (storage, changes.changes_trie_config.as_ref()) {
|
||||
(Some(storage), Some(config)) => (storage, config),
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::trie_backend_essence::TrieBackendEssence;
|
||||
use crate::changes_trie::{AnchorBlockId, Configuration, Storage, BlockNumber};
|
||||
use crate::changes_trie::storage::TrieBackendAdapter;
|
||||
use crate::changes_trie::input::{ChildIndex, InputKey};
|
||||
use codec::Decode;
|
||||
use codec::{Decode, Codec};
|
||||
|
||||
/// Get number of oldest block for which changes trie is not pruned
|
||||
/// given changes trie configuration, pruning parameter and number of
|
||||
@@ -55,7 +55,7 @@ pub fn prune<S: Storage<H, Number>, H: Hasher, Number: BlockNumber, F: FnMut(H::
|
||||
min_blocks_to_keep: Number,
|
||||
current_block: &AnchorBlockId<H::Out, Number>,
|
||||
mut remove_trie_node: F,
|
||||
) {
|
||||
) where H::Out: Codec {
|
||||
|
||||
// select range for pruning
|
||||
let (first, last) = match pruning_range(config, min_blocks_to_keep, current_block.number.clone()) {
|
||||
@@ -116,7 +116,7 @@ fn prune_trie<S: Storage<H, Number>, H: Hasher, Number: BlockNumber, F: FnMut(H:
|
||||
storage: &S,
|
||||
root: H::Out,
|
||||
remove_trie_node: &mut F,
|
||||
) {
|
||||
) where H::Out: Codec {
|
||||
|
||||
// enumerate all changes trie' keys, recording all nodes that have been 'touched'
|
||||
// (effectively - all changes trie nodes)
|
||||
@@ -221,13 +221,15 @@ mod tests {
|
||||
storage: &S,
|
||||
min_blocks_to_keep: u64,
|
||||
current_block: u64,
|
||||
) -> HashSet<H::Out> {
|
||||
) -> HashSet<H::Out> where H::Out: Codec {
|
||||
let mut pruned_trie_nodes = HashSet::new();
|
||||
prune(config,
|
||||
prune(
|
||||
config,
|
||||
storage,
|
||||
min_blocks_to_keep,
|
||||
&AnchorBlockId { hash: Default::default(), number: current_block },
|
||||
|node| { pruned_trie_nodes.insert(node); });
|
||||
|node| { pruned_trie_nodes.insert(node); },
|
||||
);
|
||||
pruned_trie_nodes
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ use primitives::{
|
||||
};
|
||||
use trie::{trie_types::Layout, MemoryDB, default_child_trie_root};
|
||||
use externalities::Extensions;
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
use std::{error, fmt, any::{Any, TypeId}};
|
||||
use log::{warn, trace};
|
||||
@@ -189,25 +190,25 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
let result = self.overlay
|
||||
.storage(key)
|
||||
.map(|x| x.map(|x| H::hash(x)))
|
||||
.unwrap_or_else(||
|
||||
self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)
|
||||
);
|
||||
.unwrap_or_else(|| self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL));
|
||||
|
||||
trace!(target: "state-trace", "{:04x}: Hash {}={:?}",
|
||||
self.id,
|
||||
HexDisplay::from(&key),
|
||||
result,
|
||||
);
|
||||
result
|
||||
result.map(|r| r.encode())
|
||||
}
|
||||
|
||||
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
let result = self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL);
|
||||
|
||||
trace!(target: "state-trace", "{:04x}: GetOriginal {}={:?}",
|
||||
self.id,
|
||||
HexDisplay::from(&key),
|
||||
@@ -216,15 +217,16 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
|
||||
fn original_storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
let result = self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL);
|
||||
|
||||
trace!(target: "state-trace", "{:04x}: GetOriginalHash {}={:?}",
|
||||
self.id,
|
||||
HexDisplay::from(&key),
|
||||
result,
|
||||
);
|
||||
result
|
||||
result.map(|r| r.encode())
|
||||
}
|
||||
|
||||
fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
@@ -246,7 +248,7 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
let result = self.overlay
|
||||
.child_storage(storage_key.as_ref(), key)
|
||||
@@ -262,7 +264,7 @@ where
|
||||
result,
|
||||
);
|
||||
|
||||
result
|
||||
result.map(|r| r.encode())
|
||||
}
|
||||
|
||||
fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
|
||||
@@ -280,7 +282,11 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
|
||||
fn original_child_storage_hash(
|
||||
&self,
|
||||
storage_key: ChildStorageKey,
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
let result = self.backend
|
||||
.child_storage_hash(storage_key.as_ref(), key)
|
||||
@@ -292,7 +298,7 @@ where
|
||||
HexDisplay::from(&key),
|
||||
result,
|
||||
);
|
||||
result
|
||||
result.map(|r| r.encode())
|
||||
}
|
||||
|
||||
fn exists_storage(&self, key: &[u8]) -> bool {
|
||||
@@ -415,14 +421,14 @@ where
|
||||
42
|
||||
}
|
||||
|
||||
fn storage_root(&mut self) -> H256 {
|
||||
fn storage_root(&mut self) -> Vec<u8> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
if let Some((_, ref root)) = self.storage_transaction {
|
||||
trace!(target: "state-trace", "{:04x}: Root (cached) {}",
|
||||
self.id,
|
||||
HexDisplay::from(&root.as_ref()),
|
||||
);
|
||||
return root.clone();
|
||||
return root.encode();
|
||||
}
|
||||
|
||||
let child_storage_keys =
|
||||
@@ -447,7 +453,7 @@ where
|
||||
self.id,
|
||||
HexDisplay::from(&root.as_ref()),
|
||||
);
|
||||
root
|
||||
root.encode()
|
||||
}
|
||||
|
||||
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
|
||||
@@ -455,6 +461,7 @@ where
|
||||
if self.storage_transaction.is_some() {
|
||||
let root = self
|
||||
.storage(storage_key.as_ref())
|
||||
.and_then(|k| Decode::decode(&mut &k[..]).ok())
|
||||
.unwrap_or(
|
||||
default_child_trie_root::<Layout<H>>(storage_key.as_ref())
|
||||
);
|
||||
@@ -463,7 +470,7 @@ where
|
||||
HexDisplay::from(&storage_key.as_ref()),
|
||||
HexDisplay::from(&root.as_ref()),
|
||||
);
|
||||
root
|
||||
root.encode()
|
||||
} else {
|
||||
let storage_key = storage_key.as_ref();
|
||||
|
||||
@@ -481,7 +488,7 @@ where
|
||||
if is_empty {
|
||||
self.overlay.set_storage(storage_key.into(), None);
|
||||
} else {
|
||||
self.overlay.set_storage(storage_key.into(), Some(root.clone()));
|
||||
self.overlay.set_storage(storage_key.into(), Some(root.encode()));
|
||||
}
|
||||
|
||||
trace!(target: "state-trace", "{:04x}: ChildRoot({}) {}",
|
||||
@@ -489,20 +496,29 @@ where
|
||||
HexDisplay::from(&storage_key.as_ref()),
|
||||
HexDisplay::from(&root.as_ref()),
|
||||
);
|
||||
root
|
||||
|
||||
root.encode()
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_changes_root(&mut self, parent_hash: H256) -> Result<Option<H256>, ()> {
|
||||
fn storage_changes_root(&mut self, parent_hash: &[u8]) -> Result<Option<Vec<u8>>, ()> {
|
||||
let _guard = panic_handler::AbortGuard::force_abort();
|
||||
|
||||
self.changes_trie_transaction = build_changes_trie::<_, T, H, N>(
|
||||
self.backend,
|
||||
self.changes_trie_storage.clone(),
|
||||
self.overlay,
|
||||
parent_hash,
|
||||
H256::decode(&mut &parent_hash[..]).map_err(|e|
|
||||
trace!(
|
||||
target: "state-trace",
|
||||
"Failed to decode changes root parent hash: {}",
|
||||
e,
|
||||
)
|
||||
)?,
|
||||
)?;
|
||||
let result = Ok(self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.clone()));
|
||||
let result = Ok(
|
||||
self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.encode())
|
||||
);
|
||||
|
||||
trace!(target: "state-trace", "{:04x}: ChangesRoot({}) {:?}",
|
||||
self.id,
|
||||
HexDisplay::from(&parent_hash.as_ref()),
|
||||
@@ -566,7 +582,7 @@ mod tests {
|
||||
let mut overlay = prepare_overlay_with_changes();
|
||||
let backend = TestBackend::default();
|
||||
let mut ext = TestExt::new(&mut overlay, &backend, None, None);
|
||||
assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None);
|
||||
assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -576,7 +592,7 @@ mod tests {
|
||||
let storage = TestChangesTrieStorage::with_blocks(vec![(100, Default::default())]);
|
||||
let backend = TestBackend::default();
|
||||
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
|
||||
assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None);
|
||||
assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -586,8 +602,8 @@ mod tests {
|
||||
let backend = TestBackend::default();
|
||||
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
|
||||
assert_eq!(
|
||||
ext.storage_changes_root(Default::default()).unwrap(),
|
||||
Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").into()),
|
||||
ext.storage_changes_root(&H256::default().encode()).unwrap(),
|
||||
Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").to_vec()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -599,8 +615,8 @@ mod tests {
|
||||
let backend = TestBackend::default();
|
||||
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
|
||||
assert_eq!(
|
||||
ext.storage_changes_root(Default::default()).unwrap(),
|
||||
Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").into()),
|
||||
ext.storage_changes_root(&H256::default().encode()).unwrap(),
|
||||
Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").to_vec()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData};
|
||||
use log::{warn, trace};
|
||||
use hash_db::Hasher;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, Codec};
|
||||
use primitives::{
|
||||
storage::well_known_keys, NativeOrEncoded, NeverNativeValue,
|
||||
traits::CodeExecutor, hexdisplay::HexDisplay, hash::H256,
|
||||
@@ -567,7 +567,7 @@ pub fn prove_child_read<B, H, I>(
|
||||
where
|
||||
B: Backend<H>,
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -584,7 +584,7 @@ pub fn prove_read_on_trie_backend<S, H, I>(
|
||||
where
|
||||
S: trie_backend_essence::TrieBackendStorage<H>,
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -606,7 +606,7 @@ pub fn prove_child_read_on_trie_backend<S, H, I>(
|
||||
where
|
||||
S: trie_backend_essence::TrieBackendStorage<H>,
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -627,7 +627,7 @@ pub fn read_proof_check<H, I>(
|
||||
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -649,7 +649,7 @@ pub fn read_child_proof_check<H, I>(
|
||||
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -673,7 +673,7 @@ pub fn read_proof_check_on_proving_backend<H>(
|
||||
) -> Result<Option<Vec<u8>>, Box<dyn Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
{
|
||||
proving_backend.storage(key).map_err(|e| Box::new(e) as Box<dyn Error>)
|
||||
}
|
||||
@@ -686,7 +686,7 @@ pub fn read_child_proof_check_on_proving_backend<H>(
|
||||
) -> Result<Option<Vec<u8>>, Box<dyn Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
{
|
||||
proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box<dyn Error>)
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ impl From<Option<Vec<u8>>> for OverlayedValue {
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use primitives::{
|
||||
Blake2Hasher, H256, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX,
|
||||
Blake2Hasher, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX,
|
||||
};
|
||||
use crate::backend::InMemory;
|
||||
use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage;
|
||||
@@ -426,7 +426,7 @@ mod tests {
|
||||
);
|
||||
const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa");
|
||||
|
||||
assert_eq!(ext.storage_root(), H256::from(ROOT));
|
||||
assert_eq!(&ext.storage_root()[..], &ROOT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, Codec};
|
||||
use log::debug;
|
||||
use hash_db::{Hasher, HashDB, EMPTY_PREFIX, Prefix};
|
||||
use trie::{
|
||||
@@ -119,6 +119,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
|
||||
where
|
||||
S: TrieBackendStorage<H>,
|
||||
H: Hasher,
|
||||
H::Out: Codec,
|
||||
{
|
||||
/// Produce proof for a key query.
|
||||
pub fn storage(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>, String> {
|
||||
@@ -145,6 +146,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
|
||||
key: &[u8]
|
||||
) -> Result<Option<Vec<u8>>, String> {
|
||||
let root = self.storage(storage_key)?
|
||||
.and_then(|r| Decode::decode(&mut &r[..]).ok())
|
||||
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key));
|
||||
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
@@ -158,7 +160,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
|
||||
read_child_trie_value_with::<Layout<H>, _, _>(
|
||||
storage_key,
|
||||
&eph,
|
||||
&root,
|
||||
&root.as_ref(),
|
||||
key,
|
||||
&mut *self.proof_recorder
|
||||
).map_err(map_e)
|
||||
@@ -199,7 +201,9 @@ pub struct ProofRecorderBackend<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hashe
|
||||
proof_recorder: ProofRecorder<H>,
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> ProvingBackend<'a, S, H> {
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> ProvingBackend<'a, S, H>
|
||||
where H::Out: Codec
|
||||
{
|
||||
/// Create new proving backend.
|
||||
pub fn new(backend: &'a TrieBackend<S, H>) -> Self {
|
||||
let proof_recorder = Default::default();
|
||||
@@ -254,7 +258,7 @@ impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
|
||||
where
|
||||
S: 'a + TrieBackendStorage<H>,
|
||||
H: 'a + Hasher,
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
{
|
||||
type Error = String;
|
||||
type Transaction = S::Overlay;
|
||||
@@ -302,7 +306,7 @@ impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
|
||||
self.0.storage_root(delta)
|
||||
}
|
||||
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
|
||||
where
|
||||
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
H::Out: Ord
|
||||
@@ -318,6 +322,7 @@ pub fn create_proof_check_backend<H>(
|
||||
) -> Result<TrieBackend<MemoryDB<H>, H>, Box<dyn Error>>
|
||||
where
|
||||
H: Hasher,
|
||||
H::Out: Codec,
|
||||
{
|
||||
let db = create_proof_check_backend_storage(proof);
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ mod tests {
|
||||
ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
|
||||
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
|
||||
const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8");
|
||||
assert_eq!(ext.storage_root(), H256::from(ROOT));
|
||||
assert_eq!(&ext.storage_root()[..], &ROOT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -22,13 +22,14 @@ use trie::{Trie, delta_trie_root, default_child_trie_root, child_delta_trie_root
|
||||
use trie::trie_types::{TrieDB, TrieError, Layout};
|
||||
use crate::trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral};
|
||||
use crate::Backend;
|
||||
use codec::{Codec, Decode};
|
||||
|
||||
/// Patricia trie-based backend. Transaction type is an overlay of changes to commit.
|
||||
pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher> {
|
||||
essence: TrieBackendEssence<S, H>,
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackend<S, H> {
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackend<S, H> where H::Out: Codec {
|
||||
/// Create new trie-based backend.
|
||||
pub fn new(storage: S, root: H::Out) -> Self {
|
||||
TrieBackend {
|
||||
@@ -64,7 +65,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> std::fmt::Debug for TrieBackend<S, H>
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
H::Out: Ord,
|
||||
H::Out: Ord + Codec,
|
||||
{
|
||||
type Error = String;
|
||||
type Transaction = S::Overlay;
|
||||
@@ -159,16 +160,17 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
(root, write_overlay)
|
||||
}
|
||||
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
|
||||
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
|
||||
where
|
||||
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
|
||||
H::Out: Ord
|
||||
H::Out: Ord,
|
||||
{
|
||||
let default_root = default_child_trie_root::<Layout<H>>(storage_key);
|
||||
|
||||
let mut write_overlay = S::Overlay::default();
|
||||
let mut root = match self.storage(storage_key) {
|
||||
Ok(value) => value.unwrap_or(default_root.clone()),
|
||||
Ok(value) =>
|
||||
value.and_then(|r| Decode::decode(&mut &r[..]).ok()).unwrap_or(default_root.clone()),
|
||||
Err(e) => {
|
||||
warn!(target: "trie", "Failed to read child storage root: {}", e);
|
||||
default_root.clone()
|
||||
@@ -181,10 +183,10 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
&mut write_overlay,
|
||||
);
|
||||
|
||||
match child_delta_trie_root::<Layout<H>, _, _, _, _>(
|
||||
match child_delta_trie_root::<Layout<H>, _, _, _, _, _>(
|
||||
storage_key,
|
||||
&mut eph,
|
||||
root.clone(),
|
||||
root,
|
||||
delta
|
||||
) {
|
||||
Ok(ret) => root = ret,
|
||||
|
||||
@@ -26,6 +26,7 @@ use trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue,
|
||||
for_keys_in_child_trie};
|
||||
use trie::trie_types::{TrieDB, TrieError, Layout};
|
||||
use crate::backend::Consolidate;
|
||||
use codec::Encode;
|
||||
|
||||
/// Patricia trie-based storage trait.
|
||||
pub trait Storage<H: Hasher>: Send + Sync {
|
||||
@@ -39,7 +40,7 @@ pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
|
||||
root: H::Out,
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out: Encode {
|
||||
/// Create new trie-based backend.
|
||||
pub fn new(storage: S, root: H::Out) -> Self {
|
||||
TrieBackendEssence {
|
||||
@@ -79,7 +80,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
|
||||
/// Get the value of child storage at given key.
|
||||
pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result<Option<Vec<u8>>, String> {
|
||||
let root = self.storage(storage_key)?
|
||||
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key));
|
||||
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode());
|
||||
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
@@ -95,7 +96,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
|
||||
/// Retrieve all entries keys of child storage and call `f` for each of those keys.
|
||||
pub fn for_keys_in_child_storage<F: FnMut(&[u8])>(&self, storage_key: &[u8], f: F) {
|
||||
let root = match self.storage(storage_key) {
|
||||
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key)),
|
||||
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode()),
|
||||
Err(e) => {
|
||||
debug!(target: "trie", "Error while iterating child storage: {}", e);
|
||||
return;
|
||||
@@ -119,9 +120,14 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
|
||||
}
|
||||
|
||||
/// Execute given closure for all keys starting with prefix.
|
||||
pub fn for_child_keys_with_prefix<F: FnMut(&[u8])>(&self, storage_key: &[u8], prefix: &[u8], mut f: F) {
|
||||
pub fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
|
||||
&self,
|
||||
storage_key: &[u8],
|
||||
prefix: &[u8],
|
||||
mut f: F,
|
||||
) {
|
||||
let root_vec = match self.storage(storage_key) {
|
||||
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key)),
|
||||
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode()),
|
||||
Err(e) => {
|
||||
debug!(target: "trie", "Error while iterating child storage: {}", e);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user