Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
45e0ee8
Genric over hasher
dvdplm Jul 11, 2018
eb26a69
WIP start adding NodeCodec
dvdplm Jul 11, 2018
acf8284
Add codec to TrieBackend
dvdplm Jul 11, 2018
90707dc
Typechecks
dvdplm Jul 11, 2018
4ccc851
Fix error type
dvdplm Jul 11, 2018
21b7892
Cleanup
dvdplm Jul 11, 2018
6b2fa02
Tests build (and fail)
dvdplm Jul 11, 2018
f331b0c
Fix tests: don't use MemoryDB::default()
dvdplm Jul 11, 2018
f0f2413
Lockfile
dvdplm Jul 11, 2018
87740d7
Address grumbles
dvdplm Jul 12, 2018
a34f614
Teach environmental! about generics
dvdplm Jul 12, 2018
c7503ad
Add Finder artifacts
dvdplm Jul 12, 2018
711da4f
whitespace
dvdplm Jul 12, 2018
a70f4a0
Merge branch 'refactor/environmental-generic-traits' into refactor/su…
dvdplm Jul 12, 2018
b4f210a
Add a toy impl of Hasher and plug it in to Externalities
dvdplm Jul 30, 2018
3b5f60b
Use `uint` and `fixed-hash` from `parity-common`
dvdplm Jul 30, 2018
1aeb495
lock file updates
dvdplm Jul 30, 2018
f7c30f4
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Jul 30, 2018
80c96a1
Make hashes Encodable/Decodable
dvdplm Jul 31, 2018
e3277ac
lock file updates
dvdplm Jul 31, 2018
d38216b
Impl FromIterator for TestExternalities so we can collect() and use map!
dvdplm Aug 1, 2018
5f19c7b
Use rustc-hex from crates
dvdplm Aug 1, 2018
848ce8f
Fix tests in runtime-io
dvdplm Aug 1, 2018
1358bb9
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Aug 1, 2018
9b8f417
lockfile shenanigans
dvdplm Aug 1, 2018
ca01909
Add a BlakeHasher impl
dvdplm Aug 1, 2018
9e42668
Use BlakeHasher in runtime-io
dvdplm Aug 1, 2018
0f77d2b
lockfile updates
dvdplm Aug 2, 2018
402c35c
ws
dvdplm Aug 2, 2018
85b5fe1
Add a Blake2/RLP-flavoured NodeCodec
dvdplm Aug 2, 2018
56649b6
Use Blake-flavoured Hasher and NodeCodec
dvdplm Aug 2, 2018
5e5e61e
lockfile
dvdplm Aug 2, 2018
fc14711
Implement PartialEq and Default for TestExternalities
dvdplm Aug 2, 2018
05d8200
Add note about limitations of environmental!
dvdplm Aug 2, 2018
65c4f64
Make it compile, but this is probably broken
dvdplm Aug 2, 2018
56f9ef6
Derive Debug so tests in executor can work
dvdplm Aug 2, 2018
eac3f25
Make executor use BlakeHasher
dvdplm Aug 2, 2018
f3422c5
ws
dvdplm Aug 3, 2018
aa40b78
WIP make client generic
dvdplm Aug 3, 2018
54a2b66
typechecks
dvdplm Aug 3, 2018
277aadd
cleanup
dvdplm Aug 3, 2018
02a302a
client tests pass
dvdplm Aug 3, 2018
dae069b
Fix client/db
dvdplm Aug 3, 2018
7a93cf7
cleanup
dvdplm Aug 3, 2018
6329abb
Fix network
dvdplm Aug 3, 2018
dc7fc67
Fix rpc
dvdplm Aug 3, 2018
d7c0935
Fix service
dvdplm Aug 3, 2018
a553f31
Make TestExternalities work better au lieu d'un HashMap
dvdplm Aug 3, 2018
9bfe799
Fix tests in council
dvdplm Aug 3, 2018
e4cefb3
Fix tests in contract
dvdplm Aug 3, 2018
6277110
Fix tests in council
dvdplm Aug 3, 2018
adc13a2
Fix democracy
dvdplm Aug 3, 2018
252bbd8
Add comment about odd-looking reexports in tests
dvdplm Aug 3, 2018
c94018c
Don't need to load branch
dvdplm Aug 3, 2018
c49609d
Fix staking
dvdplm Aug 3, 2018
0fb6dc1
Fix session
dvdplm Aug 3, 2018
6ebfc7f
Some polkadot fixes and lockfile
dvdplm Aug 3, 2018
056bffd
Fix executive
dvdplm Aug 3, 2018
ccb61a9
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Aug 3, 2018
f565cf9
fixup lockfile
dvdplm Aug 3, 2018
d11d578
Fix polkadot/api
dvdplm Aug 4, 2018
c7334b2
Fix polkadot/service
dvdplm Aug 4, 2018
b6bde9a
Fix polkadot/runtime tests
dvdplm Aug 4, 2018
08f25d3
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Aug 5, 2018
9b139b2
Fix tests in test-runtime
dvdplm Aug 6, 2018
0c82f95
Test fixes
dvdplm Aug 6, 2018
50b4b12
Fix missing component in the `std` feature
dvdplm Aug 6, 2018
111f9fd
Use PhantomData and Result from core
dvdplm Aug 6, 2018
1276733
Fix paths
dvdplm Aug 6, 2018
334e008
load heapsize on wasm
dvdplm Aug 6, 2018
2faff87
implement `HeapSizeOf` for wasm
dvdplm Aug 6, 2018
751fe9e
Add toy impl of `blake2_256` for no_std
dvdplm Aug 6, 2018
81d7278
lockfile
dvdplm Aug 6, 2018
dd551a6
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Aug 7, 2018
dcd9541
Use kvdb* from parity-common and fix errors
dvdplm Aug 7, 2018
2370a16
rebuilt lockfile
dvdplm Aug 7, 2018
0d4a4fe
Add dummy impl of `on_advance_round` for rhododendron::Context
dvdplm Aug 7, 2018
6367815
Fix build after merge
dvdplm Aug 7, 2018
cf7e338
Add HeapSizeOf bound where needed
dvdplm Aug 8, 2018
af1b17e
Sort out dependencies for no_std
dvdplm Aug 8, 2018
ca89697
Add HeapSizeOf bound where needed
dvdplm Aug 8, 2018
da711ef
use temp branch pending PR merges
dvdplm Aug 8, 2018
3b206c2
Remove unneeded tests
dvdplm Aug 8, 2018
8064c6d
Lock file and wasm artifacts
dvdplm Aug 8, 2018
0066026
lockfile
dvdplm Aug 8, 2018
bfcf5df
Use magic commit for libp2p
dvdplm Aug 8, 2018
35b29ba
Cleanup
dvdplm Aug 9, 2018
04b7065
Implement blake2_256 for no_std
dvdplm Aug 9, 2018
8152a78
Back on parity-common master
dvdplm Aug 9, 2018
cafe669
Merge branch 'master' into refactor/substrate-state-machine-generic
dvdplm Aug 9, 2018
11ea517
missing type params
dvdplm Aug 9, 2018
4d14020
Merge branch 'master' into refactor/substrate-state-machine-generic
gavofyork Aug 9, 2018
19d07db
Update Cargo.lock
gavofyork Aug 9, 2018
60df8c1
whitespace
dvdplm Aug 9, 2018
6833f7b
Merge branch 'refactor/substrate-state-machine-generic' of github.com…
dvdplm Aug 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP start adding NodeCodec
  • Loading branch information
dvdplm committed Jul 11, 2018
commit eb26a6939825f7579ee5516d13c85af85ccb2a01
29 changes: 15 additions & 14 deletions substrate/state-machine/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ use std::sync::Arc;
use hashdb::Hasher;
use rlp::Encodable;
use trie_backend::{TryIntoTrieBackend, TrieBackend};
use patricia_trie::{TrieDBMut, TrieMut, NodeCodec};

/// A state backend is used to read state data and can have changes committed
/// to it.
///
/// The clone operation (if implemented) should be cheap.
pub trait Backend<H: Hasher>: TryIntoTrieBackend<H> {
pub trait Backend<H: Hasher, C: NodeCodec<H>>: TryIntoTrieBackend<H, C> {
/// An error type when fetching data is not possible.
type Error: super::Error;

Expand Down Expand Up @@ -73,23 +74,25 @@ impl error::Error for Void {
/// In-memory backend. Fully recomputes tries on each commit but useful for
/// tests.
#[derive(Clone, PartialEq, Eq)]
pub struct InMemory<H> {
pub struct InMemory<H, C> {
inner: Arc<HashMap<Vec<u8>, Vec<u8>>>,
_marker: PhantomData<H>,
_hasher: PhantomData<H>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious: why did you opt for an underscore here?

Copy link
Contributor Author

@dvdplm dvdplm Jul 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No real good reason. I keep going back and forth on how to name my phantoms, so I end up being inconsistent. Sometimes I like marker, sometimes I name it for what it contains, sometimes with a _ prefix to signal to the reader "never mind this, it's there to make the code compile and is not relevant".

I'd like to have a rule to follow here. What do you use?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clippy states that underscore-prefixed names are expected to be in there for compile-passing-purposes only and aren't actually used. Which is the case here, and combined with a proper descriptive name, I think this is totally the appropriate way to do it, @dvdplm :) .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"compile-passing-purposes" – rofl

_codec: PhantomData<C>,
}

impl<H> Default for InMemory<H> {
impl<H, C> Default for InMemory<H, C> {
fn default() -> Self {
InMemory {
inner: Arc::new(Default::default()),
_marker: PhantomData,
_hasher: PhantomData,
_codec: PhantomData,
}
}
}

impl<H: Hasher> InMemory<H> {
impl<H: Hasher, C: NodeCodec<H>> InMemory<H, C> {
/// Copy the state, with applied updates
pub fn update(&self, changes: <Self as Backend<H>>::Transaction) -> Self {
pub fn update(&self, changes: <Self as Backend<H, C>>::Transaction) -> Self {
let mut inner: HashMap<_, _> = (&*self.inner).clone();
for (key, val) in changes {
match val {
Expand All @@ -102,15 +105,15 @@ impl<H: Hasher> InMemory<H> {
}
}

impl<H> From<HashMap<Vec<u8>, Vec<u8>>> for InMemory<H> {
impl<H, C> From<HashMap<Vec<u8>, Vec<u8>>> for InMemory<H, C> {
fn from(inner: HashMap<Vec<u8>, Vec<u8>>) -> Self {
InMemory {
inner: Arc::new(inner), _marker: PhantomData
inner: Arc::new(inner), _hasher: PhantomData, _codec: PhantomData
}
}
}

impl<H: Hasher> Backend<H> for InMemory<H> {
impl<H: Hasher, C: NodeCodec<H>> Backend<H, C> for InMemory<H, C> {
type Error = Void;
type Transaction = Vec<(Vec<u8>, Option<Vec<u8>>)>;

Expand Down Expand Up @@ -144,15 +147,13 @@ impl<H: Hasher> Backend<H> for InMemory<H> {
}
}

impl<H: Hasher> TryIntoTrieBackend<H> for InMemory<H> {
impl<H: Hasher, C: NodeCodec<H>> TryIntoTrieBackend<H, C> for InMemory<H, C> {
fn try_into_trie_backend(self) -> Option<TrieBackend<H>> {
use memorydb::MemoryDB;
use patricia_trie::{TrieDBMut, TrieMut};

let mut root = <H as Hasher>::Out::default();
let mut mdb = MemoryDB::new();
{
let mut trie = TrieDBMut::new(&mut mdb, &mut root);
let mut trie = TrieDBMut::<H, C>::new(&mut mdb, &mut root);
for (key, value) in self.inner.iter() {
if let Err(e) = trie.insert(&key, &value) {
warn!(target: "trie", "Failed to write to trie: {}", e);
Expand Down
13 changes: 8 additions & 5 deletions substrate/state-machine/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use backend::Backend;
use {Externalities, OverlayedChanges};
use hashdb::Hasher;
use rlp::Encodable;
use patricia_trie::NodeCodec;

/// Errors that can occur when interacting with the externalities.
#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -52,7 +53,7 @@ impl<B: error::Error, E: error::Error> error::Error for Error<B, E> {
}

/// Wraps a read-only backend, call executor, and current overlayed changes.
pub struct Ext<'a, H: Hasher, B: 'a + Backend<H>> {
pub struct Ext<'a, H: Hasher, C: NodeCodec<H>, B: 'a + Backend<H, C>> { //TODO: can I get rid of the trait bounds here?
// The overlayed changes to write to.
overlay: &'a mut OverlayedChanges,
// The storage backend to read from.
Expand All @@ -61,10 +62,11 @@ pub struct Ext<'a, H: Hasher, B: 'a + Backend<H>> {
transaction: Option<(B::Transaction, H::Out)>,
}

impl<'a, H, B> Ext<'a, H, B>
impl<'a, H, C, B> Ext<'a, H, C, B>
where
H: Hasher,
B: 'a + Backend<H>,
C: NodeCodec<H>,
B: 'a + Backend<H, C>,
H::Out: Ord + Encodable
{
/// Create a new `Ext` from overlayed changes and read-only backend
Expand Down Expand Up @@ -106,10 +108,11 @@ impl<'a, B: 'a + Backend> Ext<'a, B> {
}
}

impl<'a, B: 'a, H> Externalities<H> for Ext<'a, H, B>
impl<'a, B: 'a, H, C> Externalities<H> for Ext<'a, H, C, B>
where
H: Hasher,
B: 'a + Backend<H>,
C: NodeCodec<H>,
B: 'a + Backend<H, C>,
H::Out: Ord + Encodable
{
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
Expand Down
24 changes: 14 additions & 10 deletions substrate/state-machine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ extern crate rlp;
use std::collections::HashMap;
use std::collections::hash_map::Drain;
use std::fmt;
use rlp::Encodable;
use hashdb::Hasher;
use patricia_trie::NodeCodec;
use rlp::Encodable;

pub mod backend;
mod ext;
Expand Down Expand Up @@ -170,7 +171,7 @@ pub trait CodeExecutor<H: Hasher>: Sized + Send + Sync {
///
/// Note: changes to code will be in place if this call is made again. For running partial
/// blocks (e.g. a transaction at a time), ensure a different method is used.
pub fn execute<B, Exec, H>(
pub fn execute<H, C, B, Exec>(
backend: &B,
overlay: &mut OverlayedChanges,
exec: &Exec,
Expand All @@ -179,8 +180,9 @@ pub fn execute<B, Exec, H>(
) -> Result<(Vec<u8>, B::Transaction), Box<Error>>
where
H: Hasher,
C: NodeCodec<H>,
Exec: CodeExecutor<H>,
B: Backend<H>,
B: Backend<H, C>,
H::Out: Ord + Encodable
{
let result = {
Expand Down Expand Up @@ -219,29 +221,30 @@ where
///
/// Note: changes to code will be in place if this call is made again. For running partial
/// blocks (e.g. a transaction at a time), ensure a different method is used.
pub fn prove_execution<B, Exec, H>(
pub fn prove_execution<H, C, B, Exec>(
backend: B,
overlay: &mut OverlayedChanges,
exec: &Exec,
method: &str,
call_data: &[u8],
) -> Result<(Vec<u8>, Vec<Vec<u8>>, <TrieBackend<H> as Backend<H>>::Transaction), Box<Error>>
) -> Result<(Vec<u8>, Vec<Vec<u8>>, <TrieBackend<H> as Backend<H, C>>::Transaction), Box<Error>>
where
H: Hasher,
Exec: CodeExecutor<H>,
B: TryIntoTrieBackend<H>,
C: NodeCodec<H>,
B: TryIntoTrieBackend<H, C>,
H::Out: Ord + Encodable
{
let trie_backend = backend.try_into_trie_backend()
.ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box<Error>)?;
let proving_backend = proving_backend::ProvingBackend::new(trie_backend);
let (result, transaction) = execute(&proving_backend, overlay, exec, method, call_data)?;
let (result, transaction) = execute::<H, C, _, _>(&proving_backend, overlay, exec, method, call_data)?;
let proof = proving_backend.extract_proof();
Ok((result, proof, transaction))
}

/// Check execution proof, generated by `prove_execution` call.
pub fn execution_proof_check<Exec, H>(
pub fn execution_proof_check<H, C, Exec>(
root: H::Out,
proof: Vec<Vec<u8>>,
overlay: &mut OverlayedChanges,
Expand All @@ -251,11 +254,12 @@ pub fn execution_proof_check<Exec, H>(
) -> Result<(Vec<u8>, memorydb::MemoryDB<H>), Box<Error>>
where
H: Hasher,
C: NodeCodec<H>,
Exec: CodeExecutor<H>,
H::Out: Ord + Encodable
{
let backend = proving_backend::create_proof_check_backend(root, proof)?;
execute(&backend, overlay, exec, method, call_data)
let backend = proving_backend::create_proof_check_backend::<H, C>(root, proof)?;
execute::<H, C, _, _>(&backend, overlay, exec, method, call_data)
}

#[cfg(test)]
Expand Down
30 changes: 21 additions & 9 deletions substrate/state-machine/src/proving_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,28 @@
//! Proving state machine backend.

use std::cell::RefCell;
use std::marker::PhantomData;
use hashdb::{Hasher, HashDB};
use memorydb::MemoryDB;
use patricia_trie::{TrieDB, TrieError, Trie, Recorder};
use patricia_trie::{TrieDB, Trie, Recorder, NodeCodec};
use trie_backend::{TrieBackend, Ephemeral};
use {Error, ExecutionError, Backend, TryIntoTrieBackend};
use rlp::Encodable;

/// Patricia trie-based backend which also tracks all touched storage trie values.
/// These can be sent to remote node and used as a proof of execution.
pub struct ProvingBackend<H: Hasher> {
pub struct ProvingBackend<H: Hasher, C: NodeCodec<H>> {
backend: TrieBackend<H>,
proof_recorder: RefCell<Recorder<H::Out>>,
marker: PhantomData<C> // TODO: try to remove this if possible
}

impl<H: Hasher> ProvingBackend<H> {
impl<H: Hasher, C: NodeCodec<H>> ProvingBackend<H, C> {
/// Create new proving backend.
pub fn new(backend: TrieBackend<H>) -> Self {
ProvingBackend {
backend,
proof_recorder: RefCell::new(Recorder::new()),
proof_recorder: RefCell::new(Recorder::new()), marker: PhantomData
}
}

Expand All @@ -50,9 +52,10 @@ impl<H: Hasher> ProvingBackend<H> {
}
}

impl<H> Backend<H> for ProvingBackend<H>
impl<H, C> Backend<H, C> for ProvingBackend<H, C>
where
H: Hasher,
C: NodeCodec<H>,
H::Out: Ord + Encodable
{
type Error = String;
Expand All @@ -64,14 +67,16 @@ where
self.backend.backend_storage(),
&mut read_overlay,
);
let map_e = |e: Box<TrieError<H::Out, Self::Error>>| format!("Trie lookup error: {}", e);
// let map_e = |e: Box<TrieError<H::Out, Self::Error>>| format!("Trie lookup error: {}", e);
let map_e = |e| format!("Trie lookup error: {}", e);

let mut proof_recorder = self.proof_recorder.try_borrow_mut()
.expect("only fails when already borrowed; storage() is non-reentrant; qed");
TrieDB::new(&eph, &self.backend.root()).map_err(map_e)?
TrieDB::<H, C>::new(&eph, &self.backend.root()).map_err(map_e)?
.get_with(key, &mut *proof_recorder).map(|x| x.map(|val| val.to_vec())).map_err(map_e)
}

// TODO: "error[E0283]: type annotations required: cannot resolve `_: patricia_trie::NodeCodec<H>`"/"note: required because of the requirements on the impl of `backend::Backend<H, _>` for `trie_backend::TrieBackend<H>`")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also comments shouldn't be longer than 100chars, please wrap :) .

fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F) {
self.backend.for_keys_with_prefix(prefix, f)
}
Expand All @@ -87,14 +92,21 @@ where
}
}

impl<H: Hasher> TryIntoTrieBackend<H> for ProvingBackend<H> {
impl<H: Hasher, C: NodeCodec<H>> TryIntoTrieBackend<H, C> for ProvingBackend<H, C> {
fn try_into_trie_backend(self) -> Option<TrieBackend<H>> {
None
}
}

/// Create proof check backend.
pub fn create_proof_check_backend<H: Hasher>(root: H::Out, proof: Vec<Vec<u8>>) -> Result<TrieBackend<H>, Box<Error>> {
pub fn create_proof_check_backend<H, C>(
root: H::Out,
proof: Vec<Vec<u8>>
) -> Result<TrieBackend<H>, Box<Error>>
where
H: Hasher,
C: NodeCodec<H>,
{
let mut db = MemoryDB::new();
for item in proof {
db.insert(&item);
Expand Down
9 changes: 5 additions & 4 deletions substrate/state-machine/src/trie_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Backend;
use hashdb::{Hasher, HashDB, AsHashDB};
use memorydb::MemoryDB;
use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut};
use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut, NodeCodec};
use std::collections::HashMap;
use std::sync::Arc;

Expand All @@ -32,7 +32,7 @@ pub trait Storage<H: Hasher>: Send + Sync {
}

/// Try convert into trie-based backend.
pub trait TryIntoTrieBackend<H: Hasher> {
pub trait TryIntoTrieBackend<H: Hasher, C: NodeCodec<H>> {
/// Try to convert self into trie backend.
fn try_into_trie_backend(self) -> Option<TrieBackend<H>>;
}
Expand Down Expand Up @@ -82,7 +82,7 @@ impl<H: Hasher> TrieBackend<H> {
}
}

impl<H: Hasher> Backend<H> for TrieBackend<H> {
impl<H: Hasher, C: NodeCodec<H>> Backend<H, C> for TrieBackend<H> {
type Error = String;
type Transaction = MemoryDB<H>;

Expand All @@ -93,6 +93,7 @@ impl<H: Hasher> Backend<H> for TrieBackend<H> {
overlay: &mut read_overlay,
};

// TODO: this is probably wrong too
let map_e = |e: Box<TrieError<H::Out, Self::Error>>| format!("Trie lookup error: {}", e);

TrieDB::new(&eph, &self.root).map_err(map_e)?
Expand Down Expand Up @@ -181,7 +182,7 @@ impl<H: Hasher> Backend<H> for TrieBackend<H> {
}
}

impl<H: Hasher> TryIntoTrieBackend<H> for TrieBackend<H> {
impl<H: Hasher, C: NodeCodec<H>> TryIntoTrieBackend<H, C> for TrieBackend<H> {
fn try_into_trie_backend(self) -> Option<TrieBackend<H>> {
Some(self)
}
Expand Down