diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 317215e5b6..226cce363e 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -6517,7 +6517,7 @@ dependencies = [ "substrate-panic-handler 2.0.0", "substrate-primitives 2.0.0", "substrate-trie 2.0.0", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6609,7 +6609,7 @@ dependencies = [ "substrate-transaction-pool-runtime-api 2.0.0", "substrate-trie 2.0.0", "substrate-wasm-builder-runner 1.0.4", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6663,8 +6663,8 @@ dependencies = [ "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-primitives 2.0.0", - "trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-bench 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -7229,7 +7229,7 @@ dependencies = [ [[package]] name = "trie-bench" -version = "0.16.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7237,14 +7237,14 @@ dependencies = [ "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -8438,8 +8438,8 @@ dependencies = [ "checksum tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a4263b12c3d3c403274493eb805966093b53214124796552d674ca1dd5d27c2b" "checksum tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bc913647c520c959b6d21e35ed8fa6984971deca9f0a2fcb8c51207e0c56af1d" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3073600c543ed001319d7e092c46dfd8c245af1a218ec5c75eb01582660a2b3e" -"checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" +"checksum trie-bench 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "403d8ec7dbc4b46781ef18cd96b371bb9ce6ec394fe83ece75eb3bc755dfa69f" +"checksum trie-db 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "784a9813d23f18bccab728ab039c39b8a87d0d6956dcdece39e92f5cffe5076e" "checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" "checksum trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3161ba520ab28cd8e6b68e1126f1009f6e335339d1a73b978139011703264c8" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" diff --git a/substrate/primitives/state-machine/Cargo.toml b/substrate/primitives/state-machine/Cargo.toml index 3f02056647..36557803e1 100644 --- a/substrate/primitives/state-machine/Cargo.toml +++ b/substrate/primitives/state-machine/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" log = "0.4.8" parking_lot = "0.9.0" hash-db = "0.15.2" -trie-db = "0.15.2" +trie-db = "0.16.0" trie-root = "0.15.2" trie = { package = "substrate-trie", path = "../trie" } primitives = { package = "substrate-primitives", path = "../core" } diff --git a/substrate/primitives/trie/Cargo.toml b/substrate/primitives/trie/Cargo.toml index 202c9066d0..cc9d1b2dde 100644 --- a/substrate/primitives/trie/Cargo.toml +++ b/substrate/primitives/trie/Cargo.toml @@ -15,13 +15,13 @@ harness = false codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.15.2", default-features = false } +trie-db = { version = "0.16.0", default-features = false } trie-root = { version = "0.15.2", default-features = false } memory-db = { version = "0.15.2", default-features = false } primitives = { package = "substrate-primitives", path = "../core", default-features = false } [dev-dependencies] -trie-bench = "0.16.2" +trie-bench = "0.17.0" trie-standardmap = "0.15.2" criterion = "0.2.11" hex-literal = "0.2.1" diff --git a/substrate/primitives/trie/src/lib.rs b/substrate/primitives/trie/src/lib.rs index eab05bab28..de056cace1 100644 --- a/substrate/primitives/trie/src/lib.rs +++ b/substrate/primitives/trie/src/lib.rs @@ -323,7 +323,7 @@ mod tests { type Layout = super::Layout; fn hashed_null_node() -> TrieHash { - >::hashed_null_node() + ::hashed_null_node() } fn check_equivalent(input: &Vec<(&[u8], &[u8])>) { diff --git a/substrate/primitives/trie/src/node_codec.rs b/substrate/primitives/trie/src/node_codec.rs index 03cbdfce52..e31ce8cc91 100644 --- a/substrate/primitives/trie/src/node_codec.rs +++ b/substrate/primitives/trie/src/node_codec.rs @@ -17,105 +17,147 @@ //! `NodeCodec` implementation for Substrate's trie format. use rstd::marker::PhantomData; +use rstd::ops::Range; use rstd::vec::Vec; use rstd::borrow::Borrow; -use codec::{Encode, Decode, Compact}; +use codec::{Encode, Decode, Input, Compact}; use hash_db::Hasher; -use trie_db::{self, NibbleSlice, node::Node, ChildReference, +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}}; -fn take<'a>(input: &mut &'a[u8], count: usize) -> Option<&'a[u8]> { - if input.len() < count { - return None +/// 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 +/// `Read` and `io` is not in `rstd`. +struct ByteSliceInput<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> ByteSliceInput<'a> { + fn new(data: &'a [u8]) -> Self { + ByteSliceInput { + data, + offset: 0, + } + } + + fn take(&mut self, count: usize) -> Result, codec::Error> { + if self.offset + count > self.data.len() { + return Err("out of data".into()); + } + + let range = self.offset..(self.offset + count); + self.offset += count; + Ok(range) + } +} + +impl<'a> Input for ByteSliceInput<'a> { + fn remaining_len(&mut self) -> Result, codec::Error> { + let remaining = if self.offset <= self.data.len() { + Some(self.data.len() - self.offset) + } else { + None + }; + Ok(remaining) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { + let range = self.take(into.len())?; + into.copy_from_slice(&self.data[range]); + Ok(()) + } + + fn read_byte(&mut self) -> Result { + if self.offset + 1 > self.data.len() { + return Err("out of data".into()); + } + + let byte = self.data[self.offset]; + self.offset += 1; + Ok(byte) } - let r = &(*input)[..count]; - *input = &(*input)[count..]; - Some(r) } /// Concrete implementation of a `NodeCodec` with Parity Codec encoding, generic over the `Hasher` #[derive(Default, Clone)] pub struct NodeCodec(PhantomData); -impl NodeCodecT for NodeCodec { +impl NodeCodecT for NodeCodec { type Error = Error; + type HashOut = H::Out; fn hashed_null_node() -> ::Out { - H::hash(>::empty_node()) + H::hash(::empty_node()) } - fn decode(data: &[u8]) -> rstd::result::Result { - let input = &mut &*data; - let head = NodeHeader::decode(input)?; - match head { - NodeHeader::Null => Ok(Node::Empty), + fn decode_plan(data: &[u8]) -> rstd::result::Result { + let mut input = ByteSliceInput::new(data); + match NodeHeader::decode(&mut input)? { + NodeHeader::Null => Ok(NodePlan::Empty), NodeHeader::Branch(has_value, 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(input[0]) != 0 { + if padding && nibble_ops::pad_left(data[input.offset]) != 0 { return Err(Error::BadFormat); } - let nibble_data = take( - input, + let partial = input.take( (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, - ).ok_or(Error::BadFormat)?; - let nibble_slice = NibbleSlice::new_offset( - nibble_data, - nibble_ops::number_padding(nibble_count), - ); - let bitmap_slice = take(input, BITMAP_LENGTH).ok_or(Error::BadFormat)?; - let bitmap = Bitmap::decode(&bitmap_slice[..])?; + )?; + let partial_padding = nibble_ops::number_padding(nibble_count); + let bitmap_range = input.take(BITMAP_LENGTH)?; + let bitmap = Bitmap::decode(&data[bitmap_range])?; let value = if has_value { - let count = >::decode(input)?.0 as usize; - Some(take(input, count).ok_or(Error::BadFormat)?) + let count = >::decode(&mut input)?.0 as usize; + Some(input.take(count)?) } else { None }; - let mut children = [None; 16]; - + let mut children = [ + 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) { - let count = >::decode(input)?.0 as usize; - children[i] = Some(take(input, count).ok_or(Error::BadFormat)?); + let count = >::decode(&mut input)?.0 as usize; + let range = input.take(count)?; + children[i] = Some(if count == H::LENGTH { + NodeHandlePlan::Hash(range) + } else { + NodeHandlePlan::Inline(range) + }); } } - Ok(Node::NibbledBranch(nibble_slice, children, value)) + Ok(NodePlan::NibbledBranch { + partial: NibbleSlicePlan::new(partial, partial_padding), + 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(input[0]) != 0 { + if padding && nibble_ops::pad_left(data[input.offset]) != 0 { return Err(Error::BadFormat); } - let nibble_data = take( - input, + let partial = input.take( (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, - ).ok_or(Error::BadFormat)?; - let nibble_slice = NibbleSlice::new_offset( - nibble_data, - nibble_ops::number_padding(nibble_count), - ); - let count = >::decode(input)?.0 as usize; - Ok(Node::Leaf(nibble_slice, take(input, count).ok_or(Error::BadFormat)?)) + )?; + let partial_padding = nibble_ops::number_padding(nibble_count); + let count = >::decode(&mut input)?.0 as usize; + Ok(NodePlan::Leaf { + partial: NibbleSlicePlan::new(partial, partial_padding), + value: input.take(count)?, + }) } } } - fn try_decode_hash(data: &[u8]) -> Option<::Out> { - if data.len() == H::LENGTH { - let mut r = ::Out::default(); - r.as_mut().copy_from_slice(data); - Some(r) - } else { - None - } - } - fn is_empty_node(data: &[u8]) -> bool { - data == >::empty_node() + data == ::empty_node() } fn empty_node() -> &'static [u8] { diff --git a/substrate/test/utils/runtime/Cargo.toml b/substrate/test/utils/runtime/Cargo.toml index b32081a863..f89524d284 100644 --- a/substrate/test/utils/runtime/Cargo.toml +++ b/substrate/test/utils/runtime/Cargo.toml @@ -35,7 +35,7 @@ pallet-timestamp = { path = "../../../frame/timestamp", default-features = false substrate-client = { path = "../../../client", optional = true } substrate-trie = { path = "../../../primitives/trie", default-features = false } transaction-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../../../primitives/transaction-pool/runtime-api", default-features = false } -trie-db = { version = "0.15.2", default-features = false } +trie-db = { version = "0.16.0", default-features = false } [dev-dependencies] substrate-executor = { path = "../../../client/executor" }