diff --git a/Cargo.lock b/Cargo.lock index 7a4ae1beea5af..50ee694e8df3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1250,7 +1250,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3194,7 +3194,7 @@ dependencies = [ "pallet-treasury 2.0.0", "pallet-utility 2.0.0", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "sp-api 2.0.0", @@ -4903,7 +4903,7 @@ name = "rlp" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4941,7 +4941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-hex" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -5537,7 +5537,7 @@ dependencies = [ "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sc-block-builder 0.8.0", "sc-client 0.8.0", "sc-client-api 2.0.0", @@ -5661,7 +5661,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sc-client 0.8.0", "sc-client-api 2.0.0", "sc-executor 0.8.0", @@ -6385,7 +6385,7 @@ dependencies = [ "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6704,12 +6704,12 @@ dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "sp-core 2.0.0", "sp-std 2.0.0", "trie-bench 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.19.2 (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)", ] @@ -6837,7 +6837,7 @@ dependencies = [ "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sc-rpc 2.0.0", "sp-core 2.0.0", "sp-runtime 2.0.0", @@ -6928,7 +6928,7 @@ dependencies = [ "frame-system 2.0.0", "frame-system-rpc-runtime-api 2.0.0", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "pallet-babe 2.0.0", "pallet-timestamp 2.0.0", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6955,7 +6955,7 @@ dependencies = [ "sp-version 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-wasm-builder-runner 1.0.4", - "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -7501,7 +7501,7 @@ dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7520,6 +7520,19 @@ dependencies = [ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trie-db" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "trie-root" version = "0.15.2" @@ -7590,7 +7603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -8510,7 +8523,7 @@ dependencies = [ "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "828bdf600636e90c56652689f7c3823ae2072104e4b0b5e83ea984f592f12ab9" +"checksum memory-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "881736a0f68a6fae1b596bb066c5bd16d7b3ed645a4dd8ffaefd02f585abaf71" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum merlin 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0942b357c1b4d0dc43ba724674ec89c3218e6ca2b3e8269e7cb53bcecd2f6e" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" @@ -8634,7 +8647,7 @@ dependencies = [ "checksum rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d59f0e97173c514b9036cd450c195a6483ba81055c6fa0f1bff3ab563f47d44a" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" +"checksum rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" "checksum rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48f91977f4ef3be5358c15d131d3f663f6b4d7a112555bf3bf52ad23b6659e5" @@ -8739,6 +8752,7 @@ dependencies = [ "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum trie-bench 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d276e600d06806a4ac61e5d6b145a620001e6147151e60a4f1f46a784ec4baa" "checksum trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "191fda5d0106f3ed35a8c6875428b213e15c516e48129cc263dd7ad16e9a665f" +"checksum trie-db 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d747ae5b6f078df7e46477fcc7df66df9eb4f27a031cf4a7c890a8dd03d8e6" "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/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 78e32e33334df..3688404c13bba 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -15,9 +15,9 @@ harness = false codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } sp-std = { version = "2.0.0", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.18.1", default-features = false } +trie-db = { version = "0.19.2", default-features = false } trie-root = { version = "0.15.2", default-features = false } -memory-db = { version = "0.18.0", default-features = false } +memory-db = { version = "0.18.1", default-features = false } sp-core = { version = "2.0.0", default-features = false, path = "../core" } [dev-dependencies] diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index 4ca26542dd4bb..173321a9b27c2 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -1,5 +1,3 @@ -// 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 @@ -27,6 +25,8 @@ 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`. @@ -119,6 +119,51 @@ pub mod trie_types { 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 +/// into the `db`. +/// +/// For a key `K` that is included into the `db` a proof of inclusion is generated. +/// For a key `K` that is not included into the `db` a proof of non-inclusion is generated. +/// These can be later checked in [`verify_trie_proof`]. +/// +/// [`verify_trie_proof`]: ./fn.verify_trie_proof.html +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 into 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 into the proof. +/// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion into the +/// proof. +/// +/// [`generate_trie_proof`]: ./fn.generate_trie_proof.html +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, @@ -727,4 +772,89 @@ mod tests { assert_eq!(pairs, iter_pairs); } + + #[test] + fn proof_non_inclusion_works() { + let pairs = vec![ + (hex!("0102").to_vec(), hex!("01").to_vec()), + (hex!("0203").to_vec(), hex!("0405").to_vec()), + ]; + + let mut memdb = MemoryDB::default(); + let mut root = Default::default(); + populate_trie::(&mut memdb, &mut root, &pairs); + + let non_included_key: Vec = hex!("0909").to_vec(); + let proof = generate_trie_proof::( + &memdb, + root, + &[non_included_key.clone()] + ).unwrap(); + + // Verifying that the K was not included into the trie should work. + assert!(verify_trie_proof::>( + &root, + &proof, + &[(non_included_key.clone(), None)], + ).is_ok() + ); + + // Verifying that the K was included into the trie should fail. + assert!(verify_trie_proof::>( + &root, + &proof, + &[(non_included_key, Some(hex!("1010").to_vec()))], + ).is_err() + ); + } + + #[test] + fn proof_inclusion_works() { + let pairs = vec![ + (hex!("0102").to_vec(), hex!("01").to_vec()), + (hex!("0203").to_vec(), hex!("0405").to_vec()), + ]; + + let mut memdb = MemoryDB::default(); + let mut root = Default::default(); + populate_trie::(&mut memdb, &mut root, &pairs); + + let proof = generate_trie_proof::( + &memdb, + root, + &[pairs[0].0.clone()] + ).unwrap(); + + // Check that a K, V included into the proof are verified. + assert!(verify_trie_proof::( + &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::>( + &root, + &proof, + &[(pairs[0].0.clone(), None)] + ).is_err() + ); + + // K not included into the trie is not verified. + assert!(verify_trie_proof::( + &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::( + &root, + &proof, + &[(pairs[1].0.clone(), Some(pairs[1].1.clone()))] + ).is_err() + ); + } } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 35a7bdf1f7a97..b827163a1b0f7 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -35,7 +35,7 @@ pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../ sc-client = { version = "0.8", optional = true, path = "../../client" } sp-trie = { version = "2.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../primitives/transaction-pool" } -trie-db = { version = "0.18.1", default-features = false } +trie-db = { version = "0.19.2", default-features = false } [dev-dependencies] sc-executor = { version = "0.8", path = "../../client/executor" }