mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 11:41:04 +00:00
Support reference-counting state backend. (#5769)
* Optimize pinning * Ref counting state backend * Style Co-Authored-By: Wei Tang <hi@that.world> * Update Cargo.lock * Handle empty node Co-authored-by: Wei Tang <hi@that.world>
This commit is contained in:
@@ -129,11 +129,8 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(StorageKey, StorageValue)> {
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay);
|
||||
|
||||
let collect_all = || -> Result<_, Box<TrieError<H::Out>>> {
|
||||
let trie = TrieDB::<H>::new(&eph, self.essence.root())?;
|
||||
let trie = TrieDB::<H>::new(self.essence(), self.essence.root())?;
|
||||
let mut v = Vec::new();
|
||||
for x in trie.iter()? {
|
||||
let (key, value) = x?;
|
||||
@@ -153,11 +150,8 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
}
|
||||
|
||||
fn keys(&self, prefix: &[u8]) -> Vec<StorageKey> {
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay);
|
||||
|
||||
let collect_all = || -> Result<_, Box<TrieError<H::Out>>> {
|
||||
let trie = TrieDB::<H>::new(&eph, self.essence.root())?;
|
||||
let trie = TrieDB::<H>::new(self.essence(), self.essence.root())?;
|
||||
let mut v = Vec::new();
|
||||
for x in trie.iter()? {
|
||||
let (key, _) = x?;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use log::{debug, warn};
|
||||
use hash_db::{self, Hasher, EMPTY_PREFIX, Prefix};
|
||||
use hash_db::{self, Hasher, Prefix};
|
||||
use sp_trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue,
|
||||
empty_child_trie_root, read_trie_value, read_child_trie_value,
|
||||
for_keys_in_child_trie, KeySpacedDB, TrieDBIterator};
|
||||
@@ -39,6 +39,7 @@ pub trait Storage<H: Hasher>: Send + Sync {
|
||||
pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
|
||||
storage: S,
|
||||
root: H::Out,
|
||||
empty: H::Out,
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out: Encode {
|
||||
@@ -47,6 +48,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
TrieBackendEssence {
|
||||
storage,
|
||||
root,
|
||||
empty: H::hash(&[0u8]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,18 +118,13 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
child_info: Option<&ChildInfo>,
|
||||
key: &[u8],
|
||||
) -> Result<Option<StorageKey>, String> {
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
storage: &self.storage,
|
||||
overlay: &mut read_overlay,
|
||||
};
|
||||
let dyn_eph: &dyn hash_db::HashDBRef<_, _>;
|
||||
let keyspace_eph;
|
||||
if let Some(child_info) = child_info.as_ref() {
|
||||
keyspace_eph = KeySpacedDB::new(&eph, child_info.keyspace());
|
||||
keyspace_eph = KeySpacedDB::new(self, child_info.keyspace());
|
||||
dyn_eph = &keyspace_eph;
|
||||
} else {
|
||||
dyn_eph = &eph;
|
||||
dyn_eph = self;
|
||||
}
|
||||
|
||||
let trie = TrieDB::<H>::new(dyn_eph, root)
|
||||
@@ -161,15 +158,9 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
|
||||
/// Get the value of storage at given key.
|
||||
pub fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>, String> {
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
storage: &self.storage,
|
||||
overlay: &mut read_overlay,
|
||||
};
|
||||
|
||||
let map_e = |e| format!("Trie lookup error: {}", e);
|
||||
|
||||
read_trie_value::<Layout<H>, _>(&eph, &self.root, key).map_err(map_e)
|
||||
read_trie_value::<Layout<H>, _>(self, &self.root, key).map_err(map_e)
|
||||
}
|
||||
|
||||
/// Get the value of child storage at given key.
|
||||
@@ -181,15 +172,9 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
let root = self.child_root(child_info)?
|
||||
.unwrap_or(empty_child_trie_root::<Layout<H>>().encode());
|
||||
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
storage: &self.storage,
|
||||
overlay: &mut read_overlay,
|
||||
};
|
||||
|
||||
let map_e = |e| format!("Trie lookup error: {}", e);
|
||||
|
||||
read_child_trie_value::<Layout<H>, _>(child_info.keyspace(), &eph, &root, key)
|
||||
read_child_trie_value::<Layout<H>, _>(child_info.keyspace(), self, &root, key)
|
||||
.map_err(map_e)
|
||||
}
|
||||
|
||||
@@ -207,15 +192,9 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
}
|
||||
};
|
||||
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
storage: &self.storage,
|
||||
overlay: &mut read_overlay,
|
||||
};
|
||||
|
||||
if let Err(e) = for_keys_in_child_trie::<Layout<H>, _, Ephemeral<S, H>>(
|
||||
if let Err(e) = for_keys_in_child_trie::<Layout<H>, _, _>(
|
||||
child_info.keyspace(),
|
||||
&eph,
|
||||
self,
|
||||
&root,
|
||||
f,
|
||||
) {
|
||||
@@ -254,12 +233,6 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
mut f: F,
|
||||
child_info: Option<&ChildInfo>,
|
||||
) {
|
||||
let mut read_overlay = S::Overlay::default();
|
||||
let eph = Ephemeral {
|
||||
storage: &self.storage,
|
||||
overlay: &mut read_overlay,
|
||||
};
|
||||
|
||||
let mut iter = move |db| -> Result<(), Box<TrieError<H::Out>>> {
|
||||
let trie = TrieDB::<H>::new(db, root)?;
|
||||
|
||||
@@ -275,10 +248,10 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out:
|
||||
};
|
||||
|
||||
let result = if let Some(child_info) = child_info {
|
||||
let db = KeySpacedDB::new(&eph, child_info.keyspace());
|
||||
let db = KeySpacedDB::new(self, child_info.keyspace());
|
||||
iter(&db)
|
||||
} else {
|
||||
iter(&eph)
|
||||
iter(self)
|
||||
};
|
||||
if let Err(e) = result {
|
||||
debug!(target: "trie", "Error while iterating by prefix: {}", e);
|
||||
@@ -296,15 +269,6 @@ pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> {
|
||||
overlay: &'a mut S::Overlay,
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> hash_db::AsPlainDB<H::Out, DBValue>
|
||||
for Ephemeral<'a, S, H>
|
||||
{
|
||||
fn as_plain_db<'b>(&'b self) -> &'b (dyn hash_db::PlainDB<H::Out, DBValue> + 'b) { self }
|
||||
fn as_plain_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::PlainDB<H::Out, DBValue> + 'b) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> hash_db::AsHashDB<H, DBValue>
|
||||
for Ephemeral<'a, S, H>
|
||||
{
|
||||
@@ -321,43 +285,6 @@ impl<'a, S: TrieBackendStorage<H>, H: Hasher> Ephemeral<'a, S, H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: Hasher> hash_db::PlainDB<H::Out, DBValue>
|
||||
for Ephemeral<'a, S, H>
|
||||
{
|
||||
fn get(&self, key: &H::Out) -> Option<DBValue> {
|
||||
if let Some(val) = hash_db::HashDB::get(self.overlay, key, EMPTY_PREFIX) {
|
||||
Some(val)
|
||||
} else {
|
||||
match self.storage.get(&key, EMPTY_PREFIX) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
warn!(target: "trie", "Failed to read from DB: {}", e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H::Out) -> bool {
|
||||
hash_db::HashDB::get(self, key, EMPTY_PREFIX).is_some()
|
||||
}
|
||||
|
||||
fn emplace(&mut self, key: H::Out, value: DBValue) {
|
||||
hash_db::HashDB::emplace(self.overlay, key, EMPTY_PREFIX, value)
|
||||
}
|
||||
|
||||
fn remove(&mut self, key: &H::Out) {
|
||||
hash_db::HashDB::remove(self.overlay, key, EMPTY_PREFIX)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: Hasher> hash_db::PlainDBRef<H::Out, DBValue>
|
||||
for Ephemeral<'a, S, H>
|
||||
{
|
||||
fn get(&self, key: &H::Out) -> Option<DBValue> { hash_db::PlainDB::get(self, key) }
|
||||
fn contains(&self, key: &H::Out) -> bool { hash_db::PlainDB::contains(self, key) }
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + TrieBackendStorage<H>, H: Hasher> hash_db::HashDB<H, DBValue>
|
||||
for Ephemeral<'a, S, H>
|
||||
{
|
||||
@@ -438,6 +365,59 @@ impl<H: Hasher> TrieBackendStorage<H> for MemoryDB<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> hash_db::AsHashDB<H, DBValue>
|
||||
for TrieBackendEssence<S, H>
|
||||
{
|
||||
fn as_hash_db<'b>(&'b self) -> &'b (dyn hash_db::HashDB<H, DBValue> + 'b) { self }
|
||||
fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB<H, DBValue> + 'b) { self }
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> hash_db::HashDB<H, DBValue>
|
||||
for TrieBackendEssence<S, H>
|
||||
{
|
||||
fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
|
||||
if *key == self.empty {
|
||||
return Some([0u8].to_vec())
|
||||
}
|
||||
match self.storage.get(&key, prefix) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
warn!(target: "trie", "Failed to read from DB: {}", e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
|
||||
hash_db::HashDB::get(self, key, prefix).is_some()
|
||||
}
|
||||
|
||||
fn insert(&mut self, _prefix: Prefix, _value: &[u8]) -> H::Out {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn emplace(&mut self, _key: H::Out, _prefix: Prefix, _value: DBValue) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn remove(&mut self, _key: &H::Out, _prefix: Prefix) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: TrieBackendStorage<H>, H: Hasher> hash_db::HashDBRef<H, DBValue>
|
||||
for TrieBackendEssence<S, H>
|
||||
{
|
||||
fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
|
||||
hash_db::HashDB::get(self, key, prefix)
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
|
||||
hash_db::HashDB::contains(self, key, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use sp_core::{Blake2Hasher, H256};
|
||||
|
||||
Reference in New Issue
Block a user