mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 17:31:03 +00:00
Merge commit 'e5bed7ac380b6adb54b60a2a72a2a8f07f50d6c1' as 'bridges'
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
[package]
|
||||
name = "bp-runtime"
|
||||
description = "Primitives that may be used at (bridges) runtime level."
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
|
||||
hash-db = { version = "0.15.2", default-features = false }
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"frame-support/std",
|
||||
"hash-db/std",
|
||||
"num-traits/std",
|
||||
"sp-core/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"sp-state-machine/std",
|
||||
"sp-trie/std",
|
||||
]
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common 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 Bridges Common 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 Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use frame_support::Parameter;
|
||||
use num_traits::AsPrimitive;
|
||||
use sp_runtime::traits::{
|
||||
AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, MaybeMallocSizeOf, MaybeSerializeDeserialize,
|
||||
Member, SimpleBitOps,
|
||||
};
|
||||
use sp_std::str::FromStr;
|
||||
|
||||
/// Minimal Substrate-based chain representation that may be used from no_std environment.
|
||||
pub trait Chain: Send + Sync + 'static {
|
||||
/// A type that fulfills the abstract idea of what a Substrate block number is.
|
||||
// Constraits come from the associated Number type of `sp_runtime::traits::Header`
|
||||
// See here for more info:
|
||||
// https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Number
|
||||
//
|
||||
// Note that the `AsPrimitive<usize>` trait is required by the GRANDPA justification
|
||||
// verifier, and is not usually part of a Substrate Header's Number type.
|
||||
type BlockNumber: Parameter
|
||||
+ Member
|
||||
+ MaybeSerializeDeserialize
|
||||
+ sp_std::hash::Hash
|
||||
+ Copy
|
||||
+ Default
|
||||
+ MaybeDisplay
|
||||
+ AtLeast32BitUnsigned
|
||||
+ FromStr
|
||||
+ MaybeMallocSizeOf
|
||||
+ AsPrimitive<usize>
|
||||
+ Default;
|
||||
|
||||
/// A type that fulfills the abstract idea of what a Substrate hash is.
|
||||
// Constraits come from the associated Hash type of `sp_runtime::traits::Header`
|
||||
// See here for more info:
|
||||
// https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hash
|
||||
type Hash: Parameter
|
||||
+ Member
|
||||
+ MaybeSerializeDeserialize
|
||||
+ sp_std::hash::Hash
|
||||
+ Ord
|
||||
+ Copy
|
||||
+ MaybeDisplay
|
||||
+ Default
|
||||
+ SimpleBitOps
|
||||
+ AsRef<[u8]>
|
||||
+ AsMut<[u8]>
|
||||
+ MaybeMallocSizeOf;
|
||||
|
||||
/// A type that fulfills the abstract idea of what a Substrate hasher (a type
|
||||
/// that produces hashes) is.
|
||||
// Constraits come from the associated Hashing type of `sp_runtime::traits::Header`
|
||||
// See here for more info:
|
||||
// https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hashing
|
||||
type Hasher: HashT<Output = Self::Hash>;
|
||||
|
||||
/// A type that fulfills the abstract idea of what a Substrate header is.
|
||||
// See here for more info:
|
||||
// https://crates.parity.io/sp_runtime/traits/trait.Header.html
|
||||
type Header: Parameter + HeaderT<Number = Self::BlockNumber, Hash = Self::Hash> + MaybeSerializeDeserialize;
|
||||
}
|
||||
|
||||
/// Block number used by the chain.
|
||||
pub type BlockNumberOf<C> = <C as Chain>::BlockNumber;
|
||||
|
||||
/// Hash type used by the chain.
|
||||
pub type HashOf<C> = <C as Chain>::Hash;
|
||||
|
||||
/// Hasher type used by the chain.
|
||||
pub type HasherOf<C> = <C as Chain>::Hasher;
|
||||
|
||||
/// Header type used by the chain.
|
||||
pub type HeaderOf<C> = <C as Chain>::Header;
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common 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 Bridges Common 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 Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Primitives that may be used at (bridges) runtime level.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use codec::Encode;
|
||||
use sp_core::hash::H256;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_std::convert::TryFrom;
|
||||
|
||||
pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
|
||||
pub use storage_proof::{Error as StorageProofError, StorageProofChecker};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use storage_proof::craft_valid_storage_proof;
|
||||
|
||||
mod chain;
|
||||
mod storage_proof;
|
||||
|
||||
/// Use this when something must be shared among all instances.
|
||||
pub const NO_INSTANCE_ID: InstanceId = [0, 0, 0, 0];
|
||||
|
||||
/// Bridge-with-Rialto instance id.
|
||||
pub const RIALTO_BRIDGE_INSTANCE: InstanceId = *b"rlto";
|
||||
|
||||
/// Bridge-with-Millau instance id.
|
||||
pub const MILLAU_BRIDGE_INSTANCE: InstanceId = *b"mlau";
|
||||
|
||||
/// Bridge-with-Polkadot instance id.
|
||||
pub const POLKADOT_BRIDGE_INSTANCE: InstanceId = *b"pdot";
|
||||
|
||||
/// Bridge-with-Kusama instance id.
|
||||
pub const KUSAMA_BRIDGE_INSTANCE: InstanceId = *b"ksma";
|
||||
|
||||
/// Bridge-with-Rococo instance id.
|
||||
pub const ROCOCO_BRIDGE_INSTANCE: InstanceId = *b"roco";
|
||||
|
||||
/// Bridge-with-Westend instance id.
|
||||
pub const WESTEND_BRIDGE_INSTANCE: InstanceId = *b"wend";
|
||||
|
||||
/// Call-dispatch module prefix.
|
||||
pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch";
|
||||
|
||||
/// A unique prefix for entropy when generating cross-chain account IDs.
|
||||
pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/account";
|
||||
|
||||
/// A unique prefix for entropy when generating a cross-chain account ID for the Root account.
|
||||
pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/root";
|
||||
|
||||
/// Id of deployed module instance. We have a bunch of pallets that may be used in
|
||||
/// different bridges. E.g. messages pallet may be deployed twice in the same
|
||||
/// runtime to bridge ThisChain with Chain1 and Chain2. Sometimes we need to be able
|
||||
/// to identify deployed instance dynamically. This type is used for that.
|
||||
pub type InstanceId = [u8; 4];
|
||||
|
||||
/// Type of accounts on the source chain.
|
||||
pub enum SourceAccount<T> {
|
||||
/// An account that belongs to Root (priviledged origin).
|
||||
Root,
|
||||
/// A non-priviledged account.
|
||||
///
|
||||
/// The embedded account ID may or may not have a private key depending on the "owner" of the
|
||||
/// account (private key, pallet, proxy, etc.).
|
||||
Account(T),
|
||||
}
|
||||
|
||||
/// Derive an account ID from a foreign account ID.
|
||||
///
|
||||
/// This function returns an encoded Blake2 hash. It is the responsibility of the caller to ensure
|
||||
/// this can be succesfully decoded into an AccountId.
|
||||
///
|
||||
/// The `bridge_id` is used to provide extra entropy when producing account IDs. This helps prevent
|
||||
/// AccountId collisions between different bridges on a single target chain.
|
||||
///
|
||||
/// Note: If the same `bridge_id` is used across different chains (for example, if one source chain
|
||||
/// is bridged to multiple target chains), then all the derived accounts would be the same across
|
||||
/// the different chains. This could negatively impact users' privacy across chains.
|
||||
pub fn derive_account_id<AccountId>(bridge_id: InstanceId, id: SourceAccount<AccountId>) -> H256
|
||||
where
|
||||
AccountId: Encode,
|
||||
{
|
||||
match id {
|
||||
SourceAccount::Root => (ROOT_ACCOUNT_DERIVATION_PREFIX, bridge_id).using_encoded(blake2_256),
|
||||
SourceAccount::Account(id) => (ACCOUNT_DERIVATION_PREFIX, bridge_id, id).using_encoded(blake2_256),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Derive the account ID of the shared relayer fund account.
|
||||
///
|
||||
/// This account is used to collect fees for relayers that are passing messages across the bridge.
|
||||
///
|
||||
/// The account ID can be the same across different instances of `pallet-bridge-messages` if the same
|
||||
/// `bridge_id` is used.
|
||||
pub fn derive_relayer_fund_account_id(bridge_id: InstanceId) -> H256 {
|
||||
("relayer-fund-account", bridge_id).using_encoded(blake2_256).into()
|
||||
}
|
||||
|
||||
/// Anything that has size.
|
||||
pub trait Size {
|
||||
/// Return approximate size of this object (in bytes).
|
||||
///
|
||||
/// This function should be lightweight. The result should not necessary be absolutely
|
||||
/// accurate.
|
||||
fn size_hint(&self) -> u32;
|
||||
}
|
||||
|
||||
impl Size for () {
|
||||
fn size_hint(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Pre-computed size.
|
||||
pub struct PreComputedSize(pub usize);
|
||||
|
||||
impl Size for PreComputedSize {
|
||||
fn size_hint(&self) -> u32 {
|
||||
u32::try_from(self.0).unwrap_or(u32::MAX)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common 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 Bridges Common 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 Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Logic for checking Substrate storage proofs.
|
||||
|
||||
use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
|
||||
use sp_runtime::RuntimeDebug;
|
||||
use sp_std::vec::Vec;
|
||||
use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof};
|
||||
|
||||
/// 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<H>
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
root: H::Out,
|
||||
db: MemoryDB<H>,
|
||||
}
|
||||
|
||||
impl<H> StorageProofChecker<H>
|
||||
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: StorageProof) -> Result<Self, Error> {
|
||||
let db = proof.into_memory_db();
|
||||
if !db.contains(&root, EMPTY_PREFIX) {
|
||||
return Err(Error::StorageRootMismatch);
|
||||
}
|
||||
|
||||
let checker = StorageProofChecker { root, db };
|
||||
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<Option<Vec<u8>>, Error> {
|
||||
read_trie_value::<Layout<H>, _>(&self.db, &self.root, key).map_err(|_| Error::StorageValueUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RuntimeDebug, PartialEq)]
|
||||
pub enum Error {
|
||||
StorageRootMismatch,
|
||||
StorageValueUnavailable,
|
||||
}
|
||||
|
||||
/// Return valid storage proof and state root.
|
||||
///
|
||||
/// NOTE: This should only be used for **testing**.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) {
|
||||
use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend};
|
||||
|
||||
// construct storage proof
|
||||
let backend = <InMemoryBackend<sp_core::Blake2Hasher>>::from(vec![
|
||||
(None, vec![(b"key1".to_vec(), Some(b"value1".to_vec()))]),
|
||||
(None, vec![(b"key2".to_vec(), Some(b"value2".to_vec()))]),
|
||||
(None, vec![(b"key3".to_vec(), Some(b"value3".to_vec()))]),
|
||||
// Value is too big to fit in a branch node
|
||||
(None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]),
|
||||
]);
|
||||
let root = backend.storage_root(std::iter::empty()).0;
|
||||
let proof = StorageProof::new(
|
||||
prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]])
|
||||
.unwrap()
|
||||
.iter_nodes()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
(root, proof)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn storage_proof_check() {
|
||||
let (root, proof) = craft_valid_storage_proof();
|
||||
|
||||
// check proof in runtime
|
||||
let checker = <StorageProofChecker<sp_core::Blake2Hasher>>::new(root, proof.clone()).unwrap();
|
||||
assert_eq!(checker.read_value(b"key1"), Ok(Some(b"value1".to_vec())));
|
||||
assert_eq!(checker.read_value(b"key2"), Ok(Some(b"value2".to_vec())));
|
||||
assert_eq!(checker.read_value(b"key11111"), Err(Error::StorageValueUnavailable));
|
||||
assert_eq!(checker.read_value(b"key22"), Ok(None));
|
||||
|
||||
// checking proof against invalid commitment fails
|
||||
assert_eq!(
|
||||
<StorageProofChecker<sp_core::Blake2Hasher>>::new(sp_core::H256::random(), proof).err(),
|
||||
Some(Error::StorageRootMismatch)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user