diff --git a/Cargo.lock b/Cargo.lock
index 5b29614a75b1f..72d1220a5e5bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4033,6 +4033,7 @@ dependencies = [
name = "srml-bridge"
version = "0.1.0"
dependencies = [
+ "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 2.0.0",
@@ -4041,6 +4042,8 @@ dependencies = [
"srml-support 2.0.0",
"srml-system 2.0.0",
"substrate-primitives 2.0.0",
+ "substrate-state-machine 2.0.0",
+ "substrate-trie 2.0.0",
]
[[package]]
diff --git a/srml/bridge/Cargo.toml b/srml/bridge/Cargo.toml
index 804e35e78e2c8..92c93954bf186 100644
--- a/srml/bridge/Cargo.toml
+++ b/srml/bridge/Cargo.toml
@@ -8,15 +8,18 @@ edition = "2018"
[dependencies]
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false }
+hash-db = { version = "0.15.2", default-features = false }
session = { package = "srml-session", path = "../session", default-features = false, features = ["historical"] }
serde = { version = "1.0", optional = true }
sr-primitives = { path = "../../core/sr-primitives", default-features = false }
support = { package = "srml-support", path = "../support", default-features = false }
system = { package = "srml-system", path = "../system", default-features = false }
+trie = { package = "substrate-trie", path = "../../core/trie", default-features = false }
[dev-dependencies]
primitives = { package = "substrate-primitives", path = "../../core/primitives" }
runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false }
+state-machine = { package = "substrate-state-machine", path = "../../core/state-machine" }
[features]
default = ["std"]
@@ -27,5 +30,6 @@ std = [
"sr-primitives/std",
"support/std",
"system/std",
+ "trie/std",
"runtime-io/std",
]
diff --git a/srml/bridge/src/error.rs b/srml/bridge/src/error.rs
new file mode 100644
index 0000000000000..182b0883d1e62
--- /dev/null
+++ b/srml/bridge/src/error.rs
@@ -0,0 +1,25 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate 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.
+
+// Substrate 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 Substrate. If not, see .
+
+//! Common error types for the srml-bridge crate.
+
+#[derive(PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub enum Error {
+ StorageRootMismatch,
+ StorageValueUnavailable,
+}
+
diff --git a/srml/bridge/src/lib.rs b/srml/bridge/src/lib.rs
index f24653a4f7987..625e22915d21c 100644
--- a/srml/bridge/src/lib.rs
+++ b/srml/bridge/src/lib.rs
@@ -32,6 +32,9 @@
// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]
+mod error;
+mod storage_proof;
+
use codec::{Encode, Decode};
use sr_primitives::traits::{Header, Member};
use support::{
@@ -148,7 +151,7 @@ mod tests {
use primitives::{H256, Blake2Hasher};
use sr_primitives::{
- Perbill, traits::IdentityLookup, testing::Header, generic::Digest
+ Perbill, traits::{Header as HeaderT, IdentityLookup}, testing::Header, generic::Digest,
};
use support::{assert_ok, impl_outer_origin, parameter_types};
use runtime_io::with_externalities;
@@ -223,6 +226,7 @@ mod tests {
extrinsics_root: H256::default(),
digest: Digest::default(),
};
+ let test_hash = test_header.hash();
with_externalities(&mut new_test_ext(), || {
assert_eq!(MockBridge::num_bridges(), 0);
@@ -242,7 +246,7 @@ mod tests {
MockBridge::tracked_bridges(1),
Some(BridgeInfo {
last_finalized_block_number: 42,
- last_finalized_block_hash: test_header.hash(), // FIXME: This is broken
+ last_finalized_block_hash: test_hash,
last_finalized_state_root: dummy_state_root,
current_validator_set: vec![1, 2, 3],
}));
diff --git a/srml/bridge/src/storage_proof.rs b/srml/bridge/src/storage_proof.rs
new file mode 100644
index 0000000000000..8217bb3b32e2f
--- /dev/null
+++ b/srml/bridge/src/storage_proof.rs
@@ -0,0 +1,103 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate 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.
+
+// Substrate 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 Substrate. If not, see .
+
+//! Logic for checking Substrate storage proofs.
+
+use hash_db::{Hasher, HashDB, EMPTY_PREFIX};
+use trie::{MemoryDB, Trie, trie_types::TrieDB};
+
+use crate::error::Error;
+
+/// This struct is used to read storage values from a subset of a Merklized database. The "proof"
+/// is a subset of the nodes in the Merkle structure of the database, so that it provides
+/// authentication against a known Merkle root as well as the values in the database themselves.
+pub struct StorageProofChecker
+ where H: Hasher
+{
+ root: H::Out,
+ db: MemoryDB,
+}
+
+impl StorageProofChecker
+ where H: Hasher
+{
+ /// Constructs a new storage proof checker.
+ ///
+ /// This returns an error if the given proof is invalid with respect to the given root.
+ pub fn new(root: H::Out, proof: Vec>) -> Result {
+ let mut db = MemoryDB::default();
+ for item in proof {
+ db.insert(EMPTY_PREFIX, &item);
+ }
+ let checker = StorageProofChecker {
+ root,
+ db,
+ };
+ // Return error if trie would be invalid.
+ let _ = checker.trie()?;
+ Ok(checker)
+ }
+
+ /// Reads a value from the available subset of storage. If the value cannot be read due to an
+ /// incomplete or otherwise invalid proof, this returns an error.
+ pub fn read_value(&self, key: &[u8]) -> Result