mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 22:51:13 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -15,10 +15,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(feature="std")]
|
||||
use std::fmt;
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
#[cfg(feature = "std")]
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
/// Error for trie node decoding.
|
||||
@@ -35,7 +35,7 @@ impl From<codec::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
impl StdError for Error {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
@@ -45,7 +45,7 @@ impl StdError for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
@@ -20,35 +20,36 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
mod error;
|
||||
mod node_header;
|
||||
mod node_codec;
|
||||
mod node_header;
|
||||
mod storage_proof;
|
||||
mod trie_codec;
|
||||
mod trie_stream;
|
||||
|
||||
use sp_std::{boxed::Box, marker::PhantomData, vec::Vec, borrow::Borrow};
|
||||
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, CompactProof};
|
||||
/// 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};
|
||||
use hash_db::{Hasher, Prefix};
|
||||
pub use memory_db::prefixed_key;
|
||||
/// Various re-exports from the `memory-db` crate.
|
||||
pub use memory_db::KeyFunction;
|
||||
/// The Substrate format implementation of `NodeCodec`.
|
||||
pub use node_codec::NodeCodec;
|
||||
use sp_std::{borrow::Borrow, boxed::Box, marker::PhantomData, vec::Vec};
|
||||
pub use storage_proof::{CompactProof, StorageProof};
|
||||
/// Trie codec reexport, mainly child trie support
|
||||
/// for trie compact proof.
|
||||
pub use trie_codec::{decode_compact, encode_compact, Error as CompactProofError};
|
||||
pub use trie_db::proof::VerifyError;
|
||||
use trie_db::proof::{generate_proof, verify_proof};
|
||||
/// Various re-exports from the `trie-db` crate.
|
||||
pub use trie_db::{
|
||||
nibble_ops, CError, DBValue, Query, Recorder, Trie, TrieConfiguration, TrieDBIterator,
|
||||
TrieLayout, TrieMut,
|
||||
};
|
||||
/// The Substrate format implementation of `TrieStream`.
|
||||
pub use trie_stream::TrieStream;
|
||||
|
||||
#[derive(Default)]
|
||||
/// substrate trie layout
|
||||
@@ -62,7 +63,8 @@ impl<H: Hasher> TrieLayout for Layout<H> {
|
||||
}
|
||||
|
||||
impl<H: Hasher> TrieConfiguration for Layout<H> {
|
||||
fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out where
|
||||
fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
@@ -70,7 +72,8 @@ impl<H: Hasher> TrieConfiguration for Layout<H> {
|
||||
trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input)
|
||||
}
|
||||
|
||||
fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8> where
|
||||
fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
@@ -98,19 +101,14 @@ pub type HashDB<'a, H> = dyn hash_db::HashDB<H, trie_db::DBValue> + '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<H> = memory_db::MemoryDB<
|
||||
H, memory_db::PrefixedKey<H>, trie_db::DBValue, MemTracker
|
||||
>;
|
||||
pub type PrefixedMemoryDB<H> =
|
||||
memory_db::MemoryDB<H, memory_db::PrefixedKey<H>, trie_db::DBValue, MemTracker>;
|
||||
/// 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<H> = memory_db::MemoryDB<
|
||||
H, memory_db::HashKey<H>, trie_db::DBValue, MemTracker,
|
||||
>;
|
||||
pub type MemoryDB<H> = memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue, MemTracker>;
|
||||
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
|
||||
pub type GenericMemoryDB<H, KF> = memory_db::MemoryDB<
|
||||
H, KF, trie_db::DBValue, MemTracker
|
||||
>;
|
||||
pub type GenericMemoryDB<H, KF> = memory_db::MemoryDB<H, KF, trie_db::DBValue, MemTracker>;
|
||||
|
||||
/// Persistent trie database read-access interface for the a given hasher.
|
||||
pub type TrieDB<'a, L> = trie_db::TrieDB<'a, L>;
|
||||
@@ -147,8 +145,9 @@ pub fn generate_trie_proof<'a, L: TrieConfiguration, I, K, DB>(
|
||||
db: &DB,
|
||||
root: TrieHash<L>,
|
||||
keys: I,
|
||||
) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>> where
|
||||
I: IntoIterator<Item=&'a K>,
|
||||
) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>>
|
||||
where
|
||||
I: IntoIterator<Item = &'a K>,
|
||||
K: 'a + AsRef<[u8]>,
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
@@ -168,8 +167,9 @@ pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>(
|
||||
root: &TrieHash<L>,
|
||||
proof: &[Vec<u8>],
|
||||
items: I,
|
||||
) -> Result<(), VerifyError<TrieHash<L>, error::Error>> where
|
||||
I: IntoIterator<Item=&'a (K, Option<V>)>,
|
||||
) -> Result<(), VerifyError<TrieHash<L>, error::Error>>
|
||||
where
|
||||
I: IntoIterator<Item = &'a (K, Option<V>)>,
|
||||
K: 'a + AsRef<[u8]>,
|
||||
V: 'a + AsRef<[u8]>,
|
||||
{
|
||||
@@ -180,8 +180,9 @@ pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>(
|
||||
pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
|
||||
db: &mut DB,
|
||||
mut root: TrieHash<L>,
|
||||
delta: I
|
||||
) -> Result<TrieHash<L>, Box<TrieError<L>>> where
|
||||
delta: I,
|
||||
) -> Result<TrieHash<L>, Box<TrieError<L>>>
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: Borrow<[u8]>,
|
||||
B: Borrow<Option<V>>,
|
||||
@@ -209,7 +210,7 @@ pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
|
||||
pub fn read_trie_value<L: TrieConfiguration, DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>>(
|
||||
db: &DB,
|
||||
root: &TrieHash<L>,
|
||||
key: &[u8]
|
||||
key: &[u8],
|
||||
) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
|
||||
TrieDB::<L>::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))
|
||||
}
|
||||
@@ -217,15 +218,17 @@ pub fn read_trie_value<L: TrieConfiguration, DB: hash_db::HashDBRef<L::Hash, tri
|
||||
/// Read a value from the trie with given Query.
|
||||
pub fn read_trie_value_with<
|
||||
L: TrieConfiguration,
|
||||
Q: Query<L::Hash, Item=DBValue>,
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>
|
||||
Q: Query<L::Hash, Item = DBValue>,
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
>(
|
||||
db: &DB,
|
||||
root: &TrieHash<L>,
|
||||
key: &[u8],
|
||||
query: Q
|
||||
query: Q,
|
||||
) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
|
||||
TrieDB::<L>::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))
|
||||
TrieDB::<L>::new(&*db, root)?
|
||||
.get_with(key, query)
|
||||
.map(|x| x.map(|val| val.to_vec()))
|
||||
}
|
||||
|
||||
/// Determine the empty trie root.
|
||||
@@ -240,13 +243,11 @@ pub fn empty_child_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out
|
||||
|
||||
/// Determine a child trie root given its ordered contents, closed form. H is the default hasher,
|
||||
/// but a generic implementation may ignore this type parameter and use other hashers.
|
||||
pub fn child_trie_root<L: TrieConfiguration, I, A, B>(
|
||||
input: I,
|
||||
) -> <L::Hash as Hasher>::Out
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
pub fn child_trie_root<L: TrieConfiguration, I, A, B>(input: I) -> <L::Hash as Hasher>::Out
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
{
|
||||
L::trie_root(input)
|
||||
}
|
||||
@@ -259,33 +260,30 @@ pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD, V>(
|
||||
root_data: RD,
|
||||
delta: I,
|
||||
) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: Borrow<[u8]>,
|
||||
B: Borrow<Option<V>>,
|
||||
V: Borrow<[u8]>,
|
||||
RD: AsRef<[u8]>,
|
||||
DB: hash_db::HashDB<L::Hash, trie_db::DBValue>
|
||||
where
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: Borrow<[u8]>,
|
||||
B: Borrow<Option<V>>,
|
||||
V: Borrow<[u8]>,
|
||||
RD: AsRef<[u8]>,
|
||||
DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
let mut root = TrieHash::<L>::default();
|
||||
// root is fetched from DB, not writable by runtime, so it's always valid.
|
||||
root.as_mut().copy_from_slice(root_data.as_ref());
|
||||
|
||||
let mut db = KeySpacedDBMut::new(&mut *db, keyspace);
|
||||
delta_trie_root::<L, _, _, _, _, _>(
|
||||
&mut db,
|
||||
root,
|
||||
delta,
|
||||
)
|
||||
delta_trie_root::<L, _, _, _, _, _>(&mut db, root, delta)
|
||||
}
|
||||
|
||||
/// Record all keys for a given root.
|
||||
pub fn record_all_keys<L: TrieConfiguration, DB>(
|
||||
db: &DB,
|
||||
root: &TrieHash<L>,
|
||||
recorder: &mut Recorder<TrieHash<L>>
|
||||
) -> Result<(), Box<TrieError<L>>> where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>
|
||||
recorder: &mut Recorder<TrieHash<L>>,
|
||||
) -> Result<(), Box<TrieError<L>>>
|
||||
where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
let trie = TrieDB::<L>::new(&*db, root)?;
|
||||
let iter = trie.iter()?;
|
||||
@@ -307,10 +305,10 @@ pub fn read_child_trie_value<L: TrieConfiguration, DB>(
|
||||
keyspace: &[u8],
|
||||
db: &DB,
|
||||
root_slice: &[u8],
|
||||
key: &[u8]
|
||||
key: &[u8],
|
||||
) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
|
||||
where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>
|
||||
where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
let mut root = TrieHash::<L>::default();
|
||||
// root is fetched from DB, not writable by runtime, so it's always valid.
|
||||
@@ -321,22 +319,24 @@ pub fn read_child_trie_value<L: TrieConfiguration, DB>(
|
||||
}
|
||||
|
||||
/// Read a value from the child trie with given query.
|
||||
pub fn read_child_trie_value_with<L: TrieConfiguration, Q: Query<L::Hash, Item=DBValue>, DB>(
|
||||
pub fn read_child_trie_value_with<L: TrieConfiguration, Q: Query<L::Hash, Item = DBValue>, DB>(
|
||||
keyspace: &[u8],
|
||||
db: &DB,
|
||||
root_slice: &[u8],
|
||||
key: &[u8],
|
||||
query: Q
|
||||
query: Q,
|
||||
) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
|
||||
where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>
|
||||
where
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
let mut root = TrieHash::<L>::default();
|
||||
// root is fetched from DB, not writable by runtime, so it's always valid.
|
||||
root.as_mut().copy_from_slice(root_slice);
|
||||
|
||||
let db = KeySpacedDB::new(&*db, keyspace);
|
||||
TrieDB::<L>::new(&db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))
|
||||
TrieDB::<L>::new(&db, &root)?
|
||||
.get_with(key, query)
|
||||
.map(|x| x.map(|val| val.to_vec()))
|
||||
}
|
||||
|
||||
/// `HashDB` implementation that append a encoded prefix (unique id bytes) in addition to the
|
||||
@@ -358,7 +358,8 @@ fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec<u8>, Option<u8>)
|
||||
(result, prefix.1)
|
||||
}
|
||||
|
||||
impl<'a, DB, H> KeySpacedDB<'a, DB, H> where
|
||||
impl<'a, DB, H> KeySpacedDB<'a, DB, H>
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
/// instantiate new keyspaced db
|
||||
@@ -367,7 +368,8 @@ impl<'a, DB, H> KeySpacedDB<'a, DB, H> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, DB, H> KeySpacedDBMut<'a, DB, H> where
|
||||
impl<'a, DB, H> KeySpacedDBMut<'a, DB, H>
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
/// instantiate new keyspaced db
|
||||
@@ -376,7 +378,8 @@ impl<'a, DB, H> KeySpacedDBMut<'a, DB, H> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H> where
|
||||
impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H>
|
||||
where
|
||||
DB: hash_db::HashDBRef<H, T>,
|
||||
H: Hasher,
|
||||
T: From<&'static [u8]>,
|
||||
@@ -392,7 +395,8 @@ impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H> where
|
||||
impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H>
|
||||
where
|
||||
DB: hash_db::HashDB<H, T>,
|
||||
H: Hasher,
|
||||
T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
|
||||
@@ -423,12 +427,15 @@ impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, DB, H, T> hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H> where
|
||||
impl<'a, DB, H, T> hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H>
|
||||
where
|
||||
DB: hash_db::HashDB<H, T>,
|
||||
H: Hasher,
|
||||
T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
|
||||
{
|
||||
fn as_hash_db(&self) -> &dyn hash_db::HashDB<H, T> { &*self }
|
||||
fn as_hash_db(&self) -> &dyn hash_db::HashDB<H, T> {
|
||||
&*self
|
||||
}
|
||||
|
||||
fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB<H, T> + 'b) {
|
||||
&mut *self
|
||||
@@ -447,12 +454,12 @@ mod trie_constants {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::{Encode, Decode, Compact};
|
||||
use sp_core::Blake2Hasher;
|
||||
use codec::{Compact, Decode, Encode};
|
||||
use hash_db::{HashDB, Hasher};
|
||||
use trie_db::{DBValue, TrieMut, Trie, NodeCodec as NodeCodecT};
|
||||
use trie_standardmap::{Alphabet, ValueMode, StandardMap};
|
||||
use hex_literal::hex;
|
||||
use sp_core::Blake2Hasher;
|
||||
use trie_db::{DBValue, NodeCodec as NodeCodecT, Trie, TrieMut};
|
||||
use trie_standardmap::{Alphabet, StandardMap, ValueMode};
|
||||
|
||||
type Layout = super::Layout<Blake2Hasher>;
|
||||
|
||||
@@ -491,7 +498,8 @@ mod tests {
|
||||
let t = TrieDB::<T>::new(&mut memdb, &root).unwrap();
|
||||
assert_eq!(
|
||||
input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::<Vec<_>>(),
|
||||
t.iter().unwrap()
|
||||
t.iter()
|
||||
.unwrap()
|
||||
.map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
@@ -505,9 +513,11 @@ mod tests {
|
||||
let mut empty = TrieDBMut::<Layout>::new(&mut db, &mut root);
|
||||
empty.commit();
|
||||
let root1 = empty.root().as_ref().to_vec();
|
||||
let root2: Vec<u8> = Layout::trie_root::<_, Vec<u8>, Vec<u8>>(
|
||||
std::iter::empty(),
|
||||
).as_ref().iter().cloned().collect();
|
||||
let root2: Vec<u8> = Layout::trie_root::<_, Vec<u8>, Vec<u8>>(std::iter::empty())
|
||||
.as_ref()
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
assert_eq!(root1, root2);
|
||||
}
|
||||
@@ -528,20 +538,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn branch_is_equivalent() {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &[0x10][..]),
|
||||
(&[0xba][..], &[0x11][..]),
|
||||
];
|
||||
let input: Vec<(&[u8], &[u8])> =
|
||||
vec![(&[0xaa][..], &[0x10][..]), (&[0xba][..], &[0x11][..])];
|
||||
check_equivalent::<Layout>(&input);
|
||||
check_iteration::<Layout>(&input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extension_and_branch_is_equivalent() {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &[0x10][..]),
|
||||
(&[0xab][..], &[0x11][..]),
|
||||
];
|
||||
let input: Vec<(&[u8], &[u8])> =
|
||||
vec![(&[0xaa][..], &[0x10][..]), (&[0xab][..], &[0x11][..])];
|
||||
check_equivalent::<Layout>(&input);
|
||||
check_iteration::<Layout>(&input);
|
||||
}
|
||||
@@ -567,7 +573,7 @@ mod tests {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &[0xa0][..]),
|
||||
(&[0xaa, 0xaa][..], &[0xaa][..]),
|
||||
(&[0xaa, 0xbb][..], &[0xab][..])
|
||||
(&[0xaa, 0xbb][..], &[0xab][..]),
|
||||
];
|
||||
check_equivalent::<Layout>(&input);
|
||||
check_iteration::<Layout>(&input);
|
||||
@@ -590,7 +596,10 @@ mod tests {
|
||||
#[test]
|
||||
fn single_long_leaf_is_equivalent() {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]),
|
||||
(
|
||||
&[0xaa][..],
|
||||
&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
|
||||
),
|
||||
(&[0xba][..], &[0x11][..]),
|
||||
];
|
||||
check_equivalent::<Layout>(&input);
|
||||
@@ -600,8 +609,14 @@ mod tests {
|
||||
#[test]
|
||||
fn two_long_leaves_is_equivalent() {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]),
|
||||
(&[0xba][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..])
|
||||
(
|
||||
&[0xaa][..],
|
||||
&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
|
||||
),
|
||||
(
|
||||
&[0xba][..],
|
||||
&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
|
||||
),
|
||||
];
|
||||
check_equivalent::<Layout>(&input);
|
||||
check_iteration::<Layout>(&input);
|
||||
@@ -610,11 +625,11 @@ mod tests {
|
||||
fn populate_trie<'db, T: TrieConfiguration>(
|
||||
db: &'db mut dyn HashDB<T::Hash, DBValue>,
|
||||
root: &'db mut TrieHash<T>,
|
||||
v: &[(Vec<u8>, Vec<u8>)]
|
||||
v: &[(Vec<u8>, Vec<u8>)],
|
||||
) -> TrieDBMut<'db, T> {
|
||||
let mut t = TrieDBMut::<T>::new(db, root);
|
||||
for i in 0..v.len() {
|
||||
let key: &[u8]= &v[i].0;
|
||||
let key: &[u8] = &v[i].0;
|
||||
let val: &[u8] = &v[i].1;
|
||||
t.insert(key, val).unwrap();
|
||||
}
|
||||
@@ -626,7 +641,7 @@ mod tests {
|
||||
v: &[(Vec<u8>, Vec<u8>)],
|
||||
) {
|
||||
for i in v {
|
||||
let key: &[u8]= &i.0;
|
||||
let key: &[u8] = &i.0;
|
||||
t.remove(key).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -644,7 +659,8 @@ mod tests {
|
||||
journal_key: 0,
|
||||
value_mode: ValueMode::Index,
|
||||
count: 100,
|
||||
}.make_with(seed.as_fixed_bytes_mut());
|
||||
}
|
||||
.make_with(seed.as_fixed_bytes_mut());
|
||||
|
||||
let real = Layout::trie_root(x.clone());
|
||||
let mut memdb = MemoryDB::default();
|
||||
@@ -690,17 +706,18 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn codec_trie_single_tuple() {
|
||||
let input = vec![
|
||||
(vec![0xaa], vec![0xbb])
|
||||
];
|
||||
let input = vec![(vec![0xaa], vec![0xbb])];
|
||||
let trie = Layout::trie_root_unhashed::<_, _, _>(input);
|
||||
println!("trie: {:#x?}", trie);
|
||||
assert_eq!(trie, vec![
|
||||
0x42, // leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02)
|
||||
0xaa, // key data
|
||||
to_compact(1), // length of value in bytes as Compact
|
||||
0xbb // value data
|
||||
]);
|
||||
assert_eq!(
|
||||
trie,
|
||||
vec![
|
||||
0x42, // leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02)
|
||||
0xaa, // key data
|
||||
to_compact(1), // length of value in bytes as Compact
|
||||
0xbb // value data
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -709,21 +726,21 @@ mod tests {
|
||||
let trie = Layout::trie_root_unhashed::<_, _, _>(input);
|
||||
println!("trie: {:#x?}", trie);
|
||||
let mut ex = Vec::<u8>::new();
|
||||
ex.push(0x80); // branch, no value (0b_10..) no nibble
|
||||
ex.push(0x12); // slots 1 & 4 are taken from 0-7
|
||||
ex.push(0x00); // no slots from 8-15
|
||||
ex.push(to_compact(0x05)); // first slot: LEAF, 5 bytes long.
|
||||
ex.push(0x43); // leaf 0x40 with 3 nibbles
|
||||
ex.push(0x03); // first nibble
|
||||
ex.push(0x14); // second & third nibble
|
||||
ex.push(to_compact(0x01)); // 1 byte data
|
||||
ex.push(0xff); // value data
|
||||
ex.push(to_compact(0x05)); // second slot: LEAF, 5 bytes long.
|
||||
ex.push(0x43); // leaf with 3 nibbles
|
||||
ex.push(0x08); // first nibble
|
||||
ex.push(0x19); // second & third nibble
|
||||
ex.push(to_compact(0x01)); // 1 byte data
|
||||
ex.push(0xfe); // value data
|
||||
ex.push(0x80); // branch, no value (0b_10..) no nibble
|
||||
ex.push(0x12); // slots 1 & 4 are taken from 0-7
|
||||
ex.push(0x00); // no slots from 8-15
|
||||
ex.push(to_compact(0x05)); // first slot: LEAF, 5 bytes long.
|
||||
ex.push(0x43); // leaf 0x40 with 3 nibbles
|
||||
ex.push(0x03); // first nibble
|
||||
ex.push(0x14); // second & third nibble
|
||||
ex.push(to_compact(0x01)); // 1 byte data
|
||||
ex.push(0xff); // value data
|
||||
ex.push(to_compact(0x05)); // second slot: LEAF, 5 bytes long.
|
||||
ex.push(0x43); // leaf with 3 nibbles
|
||||
ex.push(0x08); // first nibble
|
||||
ex.push(0x19); // second & third nibble
|
||||
ex.push(to_compact(0x01)); // 1 byte data
|
||||
ex.push(0xfe); // value data
|
||||
|
||||
assert_eq!(trie, ex);
|
||||
}
|
||||
@@ -763,27 +780,25 @@ mod tests {
|
||||
populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
|
||||
|
||||
let non_included_key: Vec<u8> = hex!("0909").to_vec();
|
||||
let proof = generate_trie_proof::<Layout, _, _, _>(
|
||||
&memdb,
|
||||
root,
|
||||
&[non_included_key.clone()]
|
||||
).unwrap();
|
||||
let proof =
|
||||
generate_trie_proof::<Layout, _, _, _>(&memdb, root, &[non_included_key.clone()])
|
||||
.unwrap();
|
||||
|
||||
// Verifying that the K was not included into the trie should work.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key.clone(), None)],
|
||||
).is_ok()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key.clone(), None)],
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
// Verifying that the K was included into the trie should fail.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key, Some(hex!("1010").to_vec()))],
|
||||
).is_err()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key, Some(hex!("1010").to_vec()))],
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -797,71 +812,71 @@ mod tests {
|
||||
let mut root = Default::default();
|
||||
populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
|
||||
|
||||
let proof = generate_trie_proof::<Layout, _, _, _>(
|
||||
&memdb,
|
||||
root,
|
||||
&[pairs[0].0.clone()]
|
||||
).unwrap();
|
||||
let proof =
|
||||
generate_trie_proof::<Layout, _, _, _>(&memdb, root, &[pairs[0].0.clone()]).unwrap();
|
||||
|
||||
// Check that a K, V included into the proof are verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
|
||||
).is_ok()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
// Absence of the V is not verified with the proof that has K, V included.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), None)]
|
||||
).is_err()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), None)]
|
||||
)
|
||||
.is_err());
|
||||
|
||||
// K not included into the trie is not verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(hex!("4242").to_vec(), Some(pairs[0].1.clone()))]
|
||||
).is_err()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(hex!("4242").to_vec(), Some(pairs[0].1.clone()))]
|
||||
)
|
||||
.is_err());
|
||||
|
||||
// K included into the trie but not included into the proof is not verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
|
||||
).is_err()
|
||||
);
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_storage_root_with_proof_works_independently_from_the_delta_order() {
|
||||
let proof = StorageProof::decode(&mut &include_bytes!("../test-res/proof")[..]).unwrap();
|
||||
let storage_root = sp_core::H256::decode(
|
||||
&mut &include_bytes!("../test-res/storage_root")[..],
|
||||
).unwrap();
|
||||
let storage_root =
|
||||
sp_core::H256::decode(&mut &include_bytes!("../test-res/storage_root")[..]).unwrap();
|
||||
// Delta order that is "invalid" so that it would require a different proof.
|
||||
let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
|
||||
&mut &include_bytes!("../test-res/invalid-delta-order")[..],
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
// Delta order that is "valid"
|
||||
let valid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
|
||||
&mut &include_bytes!("../test-res/valid-delta-order")[..],
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let proof_db = proof.into_memory_db::<Blake2Hasher>();
|
||||
let first_storage_root = delta_trie_root::<Layout, _, _, _, _, _>(
|
||||
&mut proof_db.clone(),
|
||||
storage_root,
|
||||
valid_delta,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
let second_storage_root = delta_trie_root::<Layout, _, _, _, _, _>(
|
||||
&mut proof_db.clone(),
|
||||
storage_root,
|
||||
invalid_delta,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(first_storage_root, second_storage_root);
|
||||
}
|
||||
|
||||
@@ -17,17 +17,16 @@
|
||||
|
||||
//! `NodeCodec` implementation for Substrate's trie format.
|
||||
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_std::ops::Range;
|
||||
use sp_std::vec::Vec;
|
||||
use sp_std::borrow::Borrow;
|
||||
use codec::{Encode, Decode, Input, Compact};
|
||||
use super::node_header::{NodeHeader, NodeKind};
|
||||
use crate::{error::Error, trie_constants};
|
||||
use codec::{Compact, Decode, Encode, Input};
|
||||
use hash_db::Hasher;
|
||||
use trie_db::{self, node::{NibbleSlicePlan, NodePlan, NodeHandlePlan}, ChildReference,
|
||||
nibble_ops, Partial, NodeCodec as NodeCodecT};
|
||||
use crate::error::Error;
|
||||
use crate::trie_constants;
|
||||
use super::{node_header::{NodeHeader, NodeKind}};
|
||||
use sp_std::{borrow::Borrow, marker::PhantomData, ops::Range, vec::Vec};
|
||||
use trie_db::{
|
||||
self, nibble_ops,
|
||||
node::{NibbleSlicePlan, NodeHandlePlan, NodePlan},
|
||||
ChildReference, NodeCodec as NodeCodecT, Partial,
|
||||
};
|
||||
|
||||
/// Helper struct for trie node decoder. This implements `codec::Input` on a byte slice, while
|
||||
/// tracking the absolute position. This is similar to `std::io::Cursor` but does not implement
|
||||
@@ -39,15 +38,12 @@ struct ByteSliceInput<'a> {
|
||||
|
||||
impl<'a> ByteSliceInput<'a> {
|
||||
fn new(data: &'a [u8]) -> Self {
|
||||
ByteSliceInput {
|
||||
data,
|
||||
offset: 0,
|
||||
}
|
||||
ByteSliceInput { data, offset: 0 }
|
||||
}
|
||||
|
||||
fn take(&mut self, count: usize) -> Result<Range<usize>, codec::Error> {
|
||||
if self.offset + count > self.data.len() {
|
||||
return Err("out of data".into());
|
||||
return Err("out of data".into())
|
||||
}
|
||||
|
||||
let range = self.offset..(self.offset + count);
|
||||
@@ -58,11 +54,8 @@ impl<'a> ByteSliceInput<'a> {
|
||||
|
||||
impl<'a> Input for ByteSliceInput<'a> {
|
||||
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
|
||||
let remaining = if self.offset <= self.data.len() {
|
||||
Some(self.data.len() - self.offset)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let remaining =
|
||||
if self.offset <= self.data.len() { Some(self.data.len() - self.offset) } else { None };
|
||||
Ok(remaining)
|
||||
}
|
||||
|
||||
@@ -74,7 +67,7 @@ impl<'a> Input for ByteSliceInput<'a> {
|
||||
|
||||
fn read_byte(&mut self) -> Result<u8, codec::Error> {
|
||||
if self.offset + 1 > self.data.len() {
|
||||
return Err("out of data".into());
|
||||
return Err("out of data".into())
|
||||
}
|
||||
|
||||
let byte = self.data[self.offset];
|
||||
@@ -103,10 +96,11 @@ impl<H: Hasher> NodeCodecT for NodeCodec<H> {
|
||||
let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
|
||||
// check that the padding is valid (if any)
|
||||
if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
|
||||
return Err(Error::BadFormat);
|
||||
return Err(Error::BadFormat)
|
||||
}
|
||||
let partial = input.take(
|
||||
(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE,
|
||||
(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
|
||||
nibble_ops::NIBBLE_PER_BYTE,
|
||||
)?;
|
||||
let partial_padding = nibble_ops::number_padding(nibble_count);
|
||||
let bitmap_range = input.take(BITMAP_LENGTH)?;
|
||||
@@ -118,8 +112,8 @@ impl<H: Hasher> NodeCodecT for NodeCodec<H> {
|
||||
None
|
||||
};
|
||||
let mut children = [
|
||||
None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||
None, None, None,
|
||||
];
|
||||
for i in 0..nibble_ops::NIBBLE_LENGTH {
|
||||
if bitmap.value_at(i) {
|
||||
@@ -137,15 +131,16 @@ impl<H: Hasher> NodeCodecT for NodeCodec<H> {
|
||||
value,
|
||||
children,
|
||||
})
|
||||
}
|
||||
},
|
||||
NodeHeader::Leaf(nibble_count) => {
|
||||
let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
|
||||
// check that the padding is valid (if any)
|
||||
if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
|
||||
return Err(Error::BadFormat);
|
||||
return Err(Error::BadFormat)
|
||||
}
|
||||
let partial = input.take(
|
||||
(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE,
|
||||
(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
|
||||
nibble_ops::NIBBLE_PER_BYTE,
|
||||
)?;
|
||||
let partial_padding = nibble_ops::number_padding(nibble_count);
|
||||
let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
|
||||
@@ -153,7 +148,7 @@ impl<H: Hasher> NodeCodecT for NodeCodec<H> {
|
||||
partial: NibbleSlicePlan::new(partial, partial_padding),
|
||||
value: input.take(count)?,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,26 +194,28 @@ impl<H: Hasher> NodeCodecT for NodeCodec<H> {
|
||||
};
|
||||
let bitmap_index = output.len();
|
||||
let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH];
|
||||
(0..BITMAP_LENGTH).for_each(|_|output.push(0));
|
||||
(0..BITMAP_LENGTH).for_each(|_| output.push(0));
|
||||
if let Some(value) = maybe_value {
|
||||
value.encode_to(&mut output);
|
||||
};
|
||||
Bitmap::encode(children.map(|maybe_child| match maybe_child.borrow() {
|
||||
Some(ChildReference::Hash(h)) => {
|
||||
h.as_ref().encode_to(&mut output);
|
||||
true
|
||||
}
|
||||
&Some(ChildReference::Inline(inline_data, len)) => {
|
||||
inline_data.as_ref()[..len].encode_to(&mut output);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}), bitmap.as_mut());
|
||||
Bitmap::encode(
|
||||
children.map(|maybe_child| match maybe_child.borrow() {
|
||||
Some(ChildReference::Hash(h)) => {
|
||||
h.as_ref().encode_to(&mut output);
|
||||
true
|
||||
},
|
||||
&Some(ChildReference::Inline(inline_data, len)) => {
|
||||
inline_data.as_ref()[..len].encode_to(&mut output);
|
||||
true
|
||||
},
|
||||
None => false,
|
||||
}),
|
||||
bitmap.as_mut(),
|
||||
);
|
||||
output[bitmap_index..bitmap_index + BITMAP_LENGTH]
|
||||
.copy_from_slice(&bitmap[..BITMAP_LENGTH]);
|
||||
output
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// utils
|
||||
@@ -280,11 +277,13 @@ impl Bitmap {
|
||||
self.0 & (1u16 << i) != 0
|
||||
}
|
||||
|
||||
pub fn encode<I: Iterator<Item = bool>>(has_children: I , dest: &mut [u8]) {
|
||||
pub fn encode<I: Iterator<Item = bool>>(has_children: I, dest: &mut [u8]) {
|
||||
let mut bitmap: u16 = 0;
|
||||
let mut cursor: u16 = 1;
|
||||
for v in has_children {
|
||||
if v { bitmap |= cursor }
|
||||
if v {
|
||||
bitmap |= cursor
|
||||
}
|
||||
cursor <<= 1;
|
||||
}
|
||||
dest[0] = (bitmap % 256) as u8;
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
//! The node header.
|
||||
|
||||
use crate::trie_constants;
|
||||
use codec::{Encode, Decode, Input, Output};
|
||||
use codec::{Decode, Encode, Input, Output};
|
||||
use sp_std::iter::once;
|
||||
|
||||
/// A node header
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(sp_core::RuntimeDebug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, sp_core::RuntimeDebug)]
|
||||
pub(crate) enum NodeHeader {
|
||||
Null,
|
||||
Branch(bool, usize),
|
||||
@@ -41,7 +40,7 @@ impl Encode for NodeHeader {
|
||||
fn encode_to<T: Output + ?Sized>(&self, output: &mut T) {
|
||||
match self {
|
||||
NodeHeader::Null => output.push_byte(trie_constants::EMPTY_TRIE),
|
||||
NodeHeader::Branch(true, nibble_count) =>
|
||||
NodeHeader::Branch(true, nibble_count) =>
|
||||
encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITH_MASK, output),
|
||||
NodeHeader::Branch(false, nibble_count) =>
|
||||
encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITHOUT_MASK, output),
|
||||
@@ -57,12 +56,14 @@ impl Decode for NodeHeader {
|
||||
fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let i = input.read_byte()?;
|
||||
if i == trie_constants::EMPTY_TRIE {
|
||||
return Ok(NodeHeader::Null);
|
||||
return Ok(NodeHeader::Null)
|
||||
}
|
||||
match i & (0b11 << 6) {
|
||||
trie_constants::LEAF_PREFIX_MASK => Ok(NodeHeader::Leaf(decode_size(i, input)?)),
|
||||
trie_constants::BRANCH_WITHOUT_MASK => Ok(NodeHeader::Branch(false, decode_size(i, input)?)),
|
||||
trie_constants::BRANCH_WITH_MASK => Ok(NodeHeader::Branch(true, decode_size(i, input)?)),
|
||||
trie_constants::BRANCH_WITHOUT_MASK =>
|
||||
Ok(NodeHeader::Branch(false, decode_size(i, input)?)),
|
||||
trie_constants::BRANCH_WITH_MASK =>
|
||||
Ok(NodeHeader::Branch(true, decode_size(i, input)?)),
|
||||
// do not allow any special encoding
|
||||
_ => Err("Unallowed encoding".into()),
|
||||
}
|
||||
@@ -76,11 +77,8 @@ pub(crate) fn size_and_prefix_iterator(size: usize, prefix: u8) -> impl Iterator
|
||||
let size = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, size);
|
||||
|
||||
let l1 = sp_std::cmp::min(62, size);
|
||||
let (first_byte, mut rem) = if size == l1 {
|
||||
(once(prefix + l1 as u8), 0)
|
||||
} else {
|
||||
(once(prefix + 63), size - l1)
|
||||
};
|
||||
let (first_byte, mut rem) =
|
||||
if size == l1 { (once(prefix + l1 as u8), 0) } else { (once(prefix + 63), size - l1) };
|
||||
let next_bytes = move || {
|
||||
if rem > 0 {
|
||||
if rem < 256 {
|
||||
@@ -109,13 +107,13 @@ fn encode_size_and_prefix<W: Output + ?Sized>(size: usize, prefix: u8, out: &mut
|
||||
fn decode_size(first: u8, input: &mut impl Input) -> Result<usize, codec::Error> {
|
||||
let mut result = (first & 255u8 >> 2) as usize;
|
||||
if result < 63 {
|
||||
return Ok(result);
|
||||
return Ok(result)
|
||||
}
|
||||
result -= 1;
|
||||
while result <= trie_constants::NIBBLE_SIZE_BOUND {
|
||||
let n = input.read_byte()? as usize;
|
||||
if n < 255 {
|
||||
return Ok(result + n + 1);
|
||||
return Ok(result + n + 1)
|
||||
}
|
||||
result += 255;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use hash_db::{HashDB, Hasher};
|
||||
use sp_std::vec::Vec;
|
||||
use codec::{Encode, Decode};
|
||||
use hash_db::{Hasher, HashDB};
|
||||
|
||||
/// A proof that some set of key-value pairs are included in the storage trie. The proof contains
|
||||
/// the storage values so that the partial storage backend can be reconstructed by a verifier that
|
||||
@@ -48,9 +48,7 @@ impl StorageProof {
|
||||
/// An empty proof is capable of only proving trivial statements (ie. that an empty set of
|
||||
/// key-value pairs exist in storage).
|
||||
pub fn empty() -> Self {
|
||||
StorageProof {
|
||||
trie_nodes: Vec::new(),
|
||||
}
|
||||
StorageProof { trie_nodes: Vec::new() }
|
||||
}
|
||||
|
||||
/// Returns whether this is an empty proof.
|
||||
@@ -76,8 +74,12 @@ impl StorageProof {
|
||||
/// Merges multiple storage proofs covering potentially different sets of keys into one proof
|
||||
/// covering all keys. The merged proof output may be smaller than the aggregate size of the input
|
||||
/// proofs due to deduplication of trie nodes.
|
||||
pub fn merge<I>(proofs: I) -> Self where I: IntoIterator<Item=Self> {
|
||||
let trie_nodes = proofs.into_iter()
|
||||
pub fn merge<I>(proofs: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Self>,
|
||||
{
|
||||
let trie_nodes = proofs
|
||||
.into_iter()
|
||||
.flat_map(|proof| proof.iter_nodes())
|
||||
.collect::<sp_std::collections::btree_set::BTreeSet<_>>()
|
||||
.into_iter()
|
||||
@@ -94,7 +96,7 @@ impl StorageProof {
|
||||
) -> Result<CompactProof, crate::CompactProofError<crate::Layout<H>>> {
|
||||
crate::encode_compact::<crate::Layout<H>>(self, root)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the estimated encoded size of the compact proof.
|
||||
///
|
||||
/// Runing this operation is a slow operation (build the whole compact proof) and should only be
|
||||
@@ -104,7 +106,6 @@ impl StorageProof {
|
||||
let compact_proof = self.into_compact_proof::<H>(root);
|
||||
compact_proof.ok().map(|p| p.encoded_size())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl CompactProof {
|
||||
@@ -127,13 +128,15 @@ impl CompactProof {
|
||||
self.iter_compact_encoded_nodes(),
|
||||
expected_root,
|
||||
)?;
|
||||
Ok((StorageProof::new(db.drain().into_iter().filter_map(|kv|
|
||||
if (kv.1).1 > 0 {
|
||||
Some((kv.1).0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
).collect()), root))
|
||||
Ok((
|
||||
StorageProof::new(
|
||||
db.drain()
|
||||
.into_iter()
|
||||
.filter_map(|kv| if (kv.1).1 > 0 { Some((kv.1).0) } else { None })
|
||||
.collect(),
|
||||
),
|
||||
root,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,9 +148,7 @@ pub struct StorageProofNodeIterator {
|
||||
|
||||
impl StorageProofNodeIterator {
|
||||
fn new(proof: StorageProof) -> Self {
|
||||
StorageProofNodeIterator {
|
||||
inner: proof.trie_nodes.into_iter(),
|
||||
}
|
||||
StorageProofNodeIterator { inner: proof.trie_nodes.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,17 +21,14 @@
|
||||
//! it to substrate specific layout and child trie system.
|
||||
|
||||
use crate::{
|
||||
EMPTY_PREFIX, HashDBT, TrieHash, TrieError, TrieConfiguration,
|
||||
CompactProof, StorageProof,
|
||||
CompactProof, HashDBT, StorageProof, TrieConfiguration, TrieError, TrieHash, EMPTY_PREFIX,
|
||||
};
|
||||
use sp_std::boxed::Box;
|
||||
use sp_std::vec::Vec;
|
||||
use trie_db::Trie;
|
||||
#[cfg(feature="std")]
|
||||
use std::fmt;
|
||||
#[cfg(feature="std")]
|
||||
use sp_std::{boxed::Box, vec::Vec};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::fmt;
|
||||
use trie_db::Trie;
|
||||
|
||||
/// Error for trie node decoding.
|
||||
pub enum Error<L: TrieConfiguration> {
|
||||
@@ -55,7 +52,7 @@ impl<L: TrieConfiguration> From<Box<TrieError<L>>> for Error<L> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
impl<L: TrieConfiguration> StdError for Error<L> {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
@@ -69,14 +66,14 @@ impl<L: TrieConfiguration> StdError for Error<L> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
impl<L: TrieConfiguration> fmt::Debug for Error<L> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
<Self as fmt::Display>::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
#[cfg(feature = "std")]
|
||||
impl<L: TrieConfiguration> fmt::Display for Error<L> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@@ -84,7 +81,8 @@ impl<L: TrieConfiguration> fmt::Display for Error<L> {
|
||||
Error::TrieError(e) => write!(f, "Trie error: {}", e),
|
||||
Error::IncompleteProof => write!(f, "Incomplete proof"),
|
||||
Error::ExtraneousChildNode => write!(f, "Child node content with no root in proof"),
|
||||
Error::ExtraneousChildProof(root) => write!(f, "Proof of child trie {:x?} not in parent proof", root.as_ref()),
|
||||
Error::ExtraneousChildProof(root) =>
|
||||
write!(f, "Proof of child trie {:x?} not in parent proof", root.as_ref()),
|
||||
Error::RootMismatch(root, expected) => write!(
|
||||
f,
|
||||
"Verification error, root is {:x?}, expected: {:x?}",
|
||||
@@ -107,21 +105,19 @@ pub fn decode_compact<'a, L, DB, I>(
|
||||
encoded: I,
|
||||
expected_root: Option<&TrieHash<L>>,
|
||||
) -> Result<TrieHash<L>, Error<L>>
|
||||
where
|
||||
L: TrieConfiguration,
|
||||
DB: HashDBT<L::Hash, trie_db::DBValue> + hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
I: IntoIterator<Item = &'a [u8]>,
|
||||
where
|
||||
L: TrieConfiguration,
|
||||
DB: HashDBT<L::Hash, trie_db::DBValue> + hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
I: IntoIterator<Item = &'a [u8]>,
|
||||
{
|
||||
let mut nodes_iter = encoded.into_iter();
|
||||
let (top_root, _nb_used) = trie_db::decode_compact_from_iter::<L, _, _, _>(
|
||||
db,
|
||||
&mut nodes_iter,
|
||||
)?;
|
||||
let (top_root, _nb_used) =
|
||||
trie_db::decode_compact_from_iter::<L, _, _, _>(db, &mut nodes_iter)?;
|
||||
|
||||
// Only check root if expected root is passed as argument.
|
||||
if let Some(expected_root) = expected_root {
|
||||
if expected_root != &top_root {
|
||||
return Err(Error::RootMismatch(top_root.clone(), expected_root.clone()));
|
||||
return Err(Error::RootMismatch(top_root.clone(), expected_root.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +138,7 @@ pub fn decode_compact<'a, L, DB, I>(
|
||||
let mut root = TrieHash::<L>::default();
|
||||
// still in a proof so prevent panic
|
||||
if root.as_mut().len() != value.as_slice().len() {
|
||||
return Err(Error::InvalidChildRoot(key, value));
|
||||
return Err(Error::InvalidChildRoot(key, value))
|
||||
}
|
||||
root.as_mut().copy_from_slice(value.as_ref());
|
||||
child_tries.push(root);
|
||||
@@ -160,16 +156,14 @@ pub fn decode_compact<'a, L, DB, I>(
|
||||
}
|
||||
|
||||
if !HashDBT::<L::Hash, _>::contains(db, &top_root, EMPTY_PREFIX) {
|
||||
return Err(Error::IncompleteProof);
|
||||
return Err(Error::IncompleteProof)
|
||||
}
|
||||
|
||||
let mut previous_extracted_child_trie = None;
|
||||
for child_root in child_tries.into_iter() {
|
||||
if previous_extracted_child_trie.is_none() {
|
||||
let (top_root, _) = trie_db::decode_compact_from_iter::<L, _, _, _>(
|
||||
db,
|
||||
&mut nodes_iter,
|
||||
)?;
|
||||
let (top_root, _) =
|
||||
trie_db::decode_compact_from_iter::<L, _, _, _>(db, &mut nodes_iter)?;
|
||||
previous_extracted_child_trie = Some(top_root);
|
||||
}
|
||||
|
||||
@@ -184,11 +178,11 @@ pub fn decode_compact<'a, L, DB, I>(
|
||||
if let Some(child_root) = previous_extracted_child_trie {
|
||||
// A child root was read from proof but is not present
|
||||
// in top trie.
|
||||
return Err(Error::ExtraneousChildProof(child_root));
|
||||
return Err(Error::ExtraneousChildProof(child_root))
|
||||
}
|
||||
|
||||
if nodes_iter.next().is_some() {
|
||||
return Err(Error::ExtraneousChildNode);
|
||||
return Err(Error::ExtraneousChildNode)
|
||||
}
|
||||
|
||||
Ok(top_root)
|
||||
@@ -201,12 +195,9 @@ pub fn decode_compact<'a, L, DB, I>(
|
||||
/// Then parse all child trie root and compress main trie content first
|
||||
/// then all child trie contents.
|
||||
/// Child trie are ordered by the order of their roots in the top trie.
|
||||
pub fn encode_compact<L>(
|
||||
proof: StorageProof,
|
||||
root: TrieHash<L>,
|
||||
) -> Result<CompactProof, Error<L>>
|
||||
where
|
||||
L: TrieConfiguration,
|
||||
pub fn encode_compact<L>(proof: StorageProof, root: TrieHash<L>) -> Result<CompactProof, Error<L>>
|
||||
where
|
||||
L: TrieConfiguration,
|
||||
{
|
||||
let mut child_tries = Vec::new();
|
||||
let partial_db = proof.into_memory_db();
|
||||
@@ -223,7 +214,7 @@ pub fn encode_compact<L>(
|
||||
let mut root = TrieHash::<L>::default();
|
||||
if root.as_mut().len() != value.as_slice().len() {
|
||||
// some child trie root in top trie are not an encoded hash.
|
||||
return Err(Error::InvalidChildRoot(key.to_vec(), value.to_vec()));
|
||||
return Err(Error::InvalidChildRoot(key.to_vec(), value.to_vec()))
|
||||
}
|
||||
root.as_mut().copy_from_slice(value.as_ref());
|
||||
child_tries.push(root);
|
||||
@@ -246,7 +237,7 @@ pub fn encode_compact<L>(
|
||||
if !HashDBT::<L::Hash, _>::contains(&partial_db, &child_root, EMPTY_PREFIX) {
|
||||
// child proof are allowed to be missing (unused root can be included
|
||||
// due to trie structure modification).
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
let trie = crate::TrieDB::<L>::new(&partial_db, &child_root)?;
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
|
||||
//! `TrieStream` implementation for Substrate's trie format.
|
||||
|
||||
use hash_db::Hasher;
|
||||
use trie_root;
|
||||
use crate::{
|
||||
node_codec::Bitmap,
|
||||
node_header::{size_and_prefix_iterator, NodeKind},
|
||||
trie_constants,
|
||||
};
|
||||
use codec::Encode;
|
||||
use hash_db::Hasher;
|
||||
use sp_std::vec::Vec;
|
||||
use crate::trie_constants;
|
||||
use crate::node_header::{NodeKind, size_and_prefix_iterator};
|
||||
use crate::node_codec::Bitmap;
|
||||
use trie_root;
|
||||
|
||||
const BRANCH_NODE_NO_VALUE: u8 = 254;
|
||||
const BRANCH_NODE_WITH_VALUE: u8 = 255;
|
||||
@@ -36,41 +38,42 @@ pub struct TrieStream {
|
||||
|
||||
impl TrieStream {
|
||||
// useful for debugging but not used otherwise
|
||||
pub fn as_raw(&self) -> &[u8] { &self.buffer }
|
||||
pub fn as_raw(&self) -> &[u8] {
|
||||
&self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_node_bit_mask(has_children: impl Iterator<Item = bool>) -> (u8, u8) {
|
||||
let mut bitmap: u16 = 0;
|
||||
let mut cursor: u16 = 1;
|
||||
for v in has_children {
|
||||
if v { bitmap |= cursor }
|
||||
if v {
|
||||
bitmap |= cursor
|
||||
}
|
||||
cursor <<= 1;
|
||||
}
|
||||
((bitmap % 256 ) as u8, (bitmap / 256 ) as u8)
|
||||
((bitmap % 256) as u8, (bitmap / 256) as u8)
|
||||
}
|
||||
|
||||
|
||||
/// Create a leaf/branch node, encoding a number of nibbles.
|
||||
fn fuse_nibbles_node<'a>(nibbles: &'a [u8], kind: NodeKind) -> impl Iterator<Item = u8> + 'a {
|
||||
let size = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibbles.len());
|
||||
|
||||
let iter_start = match kind {
|
||||
NodeKind::Leaf => size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK),
|
||||
NodeKind::BranchNoValue => size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK),
|
||||
NodeKind::BranchWithValue => size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK),
|
||||
NodeKind::BranchNoValue =>
|
||||
size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK),
|
||||
NodeKind::BranchWithValue =>
|
||||
size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK),
|
||||
};
|
||||
iter_start
|
||||
.chain(if nibbles.len() % 2 == 1 { Some(nibbles[0]) } else { None })
|
||||
.chain(nibbles[nibbles.len() % 2..].chunks(2).map(|ch| ch[0] << 4 | ch[1]))
|
||||
}
|
||||
|
||||
|
||||
impl trie_root::TrieStream for TrieStream {
|
||||
|
||||
fn new() -> Self {
|
||||
TrieStream {
|
||||
buffer: Vec::new()
|
||||
}
|
||||
TrieStream { buffer: Vec::new() }
|
||||
}
|
||||
|
||||
fn append_empty_data(&mut self) {
|
||||
@@ -95,7 +98,7 @@ impl trie_root::TrieStream for TrieStream {
|
||||
self.buffer.extend(fuse_nibbles_node(partial, NodeKind::BranchNoValue));
|
||||
}
|
||||
let bm = branch_node_bit_mask(has_children);
|
||||
self.buffer.extend([bm.0,bm.1].iter());
|
||||
self.buffer.extend([bm.0, bm.1].iter());
|
||||
} else {
|
||||
debug_assert!(false, "trie stream codec only for no extension trie");
|
||||
self.buffer.extend(&branch_node(maybe_value.is_some(), has_children));
|
||||
@@ -117,7 +120,9 @@ impl trie_root::TrieStream for TrieStream {
|
||||
}
|
||||
}
|
||||
|
||||
fn out(self) -> Vec<u8> { self.buffer }
|
||||
fn out(self) -> Vec<u8> {
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_node(has_value: bool, has_children: impl Iterator<Item = bool>) -> [u8; 3] {
|
||||
@@ -126,15 +131,11 @@ fn branch_node(has_value: bool, has_children: impl Iterator<Item = bool>) -> [u8
|
||||
result
|
||||
}
|
||||
|
||||
fn branch_node_buffered<I>(has_value: bool, has_children: I, output: &mut[u8])
|
||||
where
|
||||
I: Iterator<Item = bool>,
|
||||
fn branch_node_buffered<I>(has_value: bool, has_children: I, output: &mut [u8])
|
||||
where
|
||||
I: Iterator<Item = bool>,
|
||||
{
|
||||
let first = if has_value {
|
||||
BRANCH_NODE_WITH_VALUE
|
||||
} else {
|
||||
BRANCH_NODE_NO_VALUE
|
||||
};
|
||||
let first = if has_value { BRANCH_NODE_WITH_VALUE } else { BRANCH_NODE_NO_VALUE };
|
||||
output[0] = first;
|
||||
Bitmap::encode(has_children, &mut output[1..]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user