// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
//! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie").
#![cfg_attr(not(feature = "std"), no_std)]
mod error;
mod node_header;
mod node_codec;
mod storage_proof;
mod trie_stream;
use sp_std::boxed::Box;
use sp_std::marker::PhantomData;
use sp_std::vec::Vec;
use hash_db::{Hasher, Prefix};
use trie_db::proof::{generate_proof, verify_proof};
pub use trie_db::proof::VerifyError;
/// Our `NodeCodec`-specific error.
pub use error::Error;
/// The Substrate format implementation of `TrieStream`.
pub use trie_stream::TrieStream;
/// The Substrate format implementation of `NodeCodec`.
pub use node_codec::NodeCodec;
pub use storage_proof::StorageProof;
/// Various re-exports from the `trie-db` crate.
pub use trie_db::{
Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, TrieDBIterator,
};
/// Various re-exports from the `memory-db` crate.
pub use memory_db::KeyFunction;
pub use memory_db::prefixed_key;
/// Various re-exports from the `hash-db` crate.
pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
#[derive(Default)]
/// substrate trie layout
pub struct Layout(sp_std::marker::PhantomData);
impl TrieLayout for Layout {
const USE_EXTENSION: bool = false;
type Hash = H;
type Codec = NodeCodec;
}
impl TrieConfiguration for Layout {
fn trie_root(input: I) -> ::Out where
I: IntoIterator,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
trie_root::trie_root_no_extension::(input)
}
fn trie_root_unhashed(input: I) -> Vec where
I: IntoIterator,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
trie_root::unhashed_trie_no_extension::(input)
}
fn encode_index(input: u32) -> Vec {
codec::Encode::encode(&codec::Compact(input))
}
}
/// TrieDB error over `TrieConfiguration` trait.
pub type TrieError = trie_db::TrieError, CError>;
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
pub trait AsHashDB: hash_db::AsHashDB {}
impl> AsHashDB for T {}
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
pub type HashDB<'a, H> = dyn hash_db::HashDB + 'a;
/// Reexport from `hash_db`, with genericity set for key only.
pub type PlainDB<'a, K> = dyn hash_db::PlainDB + 'a;
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
/// This uses a `KeyFunction` for prefixing keys internally (avoiding
/// key conflict for non random keys).
pub type PrefixedMemoryDB = memory_db::MemoryDB, trie_db::DBValue>;
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
/// This uses a noops `KeyFunction` (key addressing must be hashed or using
/// an encoding scheme that avoid key conflict).
pub type MemoryDB = memory_db::MemoryDB, trie_db::DBValue>;
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
pub type GenericMemoryDB = memory_db::MemoryDB;
/// Persistent trie database read-access interface for the a given hasher.
pub type TrieDB<'a, L> = trie_db::TrieDB<'a, L>;
/// Persistent trie database write-access interface for the a given hasher.
pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>;
/// Querying interface, as in `trie_db` but less generic.
pub type Lookup<'a, L, Q> = trie_db::Lookup<'a, L, Q>;
/// Hash type for a trie layout.
pub type TrieHash = <::Hash as Hasher>::Out;
/// This module is for non generic definition of trie type.
/// Only the `Hasher` trait is generic in this case.
pub mod trie_types {
pub type Layout = super::Layout;
/// Persistent trie database read-access interface for the a given hasher.
pub type TrieDB<'a, H> = super::TrieDB<'a, Layout>;
/// Persistent trie database write-access interface for the a given hasher.
pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout>;
/// Querying interface, as in `trie_db` but less generic.
pub type Lookup<'a, H, Q> = trie_db::Lookup<'a, Layout, Q>;
/// As in `trie_db`, but less generic, error type for the crate.
pub type TrieError = trie_db::TrieError;
}
/// Create a proof for a subset of keys in a trie.
///
/// The `keys` may contain any set of keys regardless of each one of them is included
/// in the `db`.
///
/// For a key `K` that is included in the `db` a proof of inclusion is generated.
/// For a key `K` that is not included in the `db` a proof of non-inclusion is generated.
/// These can be later checked in `verify_trie_proof`.
pub fn generate_trie_proof<'a, L: TrieConfiguration, I, K, DB>(
db: &DB,
root: TrieHash,
keys: I,
) -> Result>, Box>> where
I: IntoIterator,
K: 'a + AsRef<[u8]>,
DB: hash_db::HashDBRef,
{
let trie = TrieDB::::new(db, &root)?;
generate_proof(&trie, keys)
}
/// Verify a set of key-value pairs against a trie root and a proof.
///
/// Checks a set of keys with optional values for inclusion in the proof that was generated by
/// `generate_trie_proof`.
/// If the value in the pair is supplied (`(key, Some(value))`), this key-value pair will be
/// checked for inclusion in the proof.
/// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion in the
/// proof.
pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>(
root: &TrieHash,
proof: &[Vec],
items: I,
) -> Result<(), VerifyError, error::Error>> where
I: IntoIterator)>,
K: 'a + AsRef<[u8]>,
V: 'a + AsRef<[u8]>,
{
verify_proof::, _, _, _>(root, proof, items)
}
/// Determine a trie root given a hash DB and delta values.
pub fn delta_trie_root(
db: &mut DB,
mut root: TrieHash,
delta: I
) -> Result, Box>> where
I: IntoIterator)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
DB: hash_db::HashDB,
{
{
let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?;
for (key, change) in delta {
match change {
Some(val) => trie.insert(key.as_ref(), val.as_ref())?,
None => trie.remove(key.as_ref())?,
};
}
}
Ok(root)
}
/// Read a value from the trie.
pub fn read_trie_value>(
db: &DB,
root: &TrieHash,
key: &[u8]
) -> Result