Merge commit '392447f5c8f986ded2559a78457f4cd87942f393' into update-bridges-subtree-r/w

This commit is contained in:
antonio-dropulic
2021-12-01 09:46:14 +01:00
321 changed files with 28385 additions and 10466 deletions
+7 -11
View File
@@ -7,24 +7,20 @@ 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 }
codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false }
hash-db = { version = "0.15.2", default-features = false }
num-traits = { version = "0.2", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
# 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 }
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" }
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 }
[features]
default = ["std"]
@@ -15,12 +15,15 @@
// 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 num_traits::{AsPrimitive, Bounded, CheckedSub, SaturatingAdd, Zero};
use sp_runtime::{
traits::{
AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify,
},
FixedPointOperand,
};
use sp_std::str::FromStr;
use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr};
/// Minimal Substrate-based chain representation that may be used from no_std environment.
pub trait Chain: Send + Sync + 'static {
@@ -34,7 +37,7 @@ pub trait Chain: Send + Sync + 'static {
type BlockNumber: Parameter
+ Member
+ MaybeSerializeDeserialize
+ sp_std::hash::Hash
+ Hash
+ Copy
+ Default
+ MaybeDisplay
@@ -42,7 +45,10 @@ pub trait Chain: Send + Sync + 'static {
+ FromStr
+ MaybeMallocSizeOf
+ AsPrimitive<usize>
+ Default;
+ Default
// original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but
// `sp_runtime::generic::Era` requires block number -> `u64` conversion.
+ Into<u64>;
/// 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`
@@ -51,7 +57,7 @@ pub trait Chain: Send + Sync + 'static {
type Hash: Parameter
+ Member
+ MaybeSerializeDeserialize
+ sp_std::hash::Hash
+ Hash
+ Ord
+ Copy
+ MaybeDisplay
@@ -71,7 +77,48 @@ pub trait Chain: Send + Sync + 'static {
/// 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;
type Header: Parameter
+ HeaderT<Number = Self::BlockNumber, Hash = Self::Hash>
+ MaybeSerializeDeserialize;
/// The user account identifier type for the runtime.
type AccountId: Parameter
+ Member
+ MaybeSerializeDeserialize
+ Debug
+ MaybeDisplay
+ Ord
+ Default;
/// Balance of an account in native tokens.
///
/// The chain may support multiple tokens, but this particular type is for token that is used
/// to pay for transaction dispatch, to reward different relayers (headers, messages), etc.
type Balance: AtLeast32BitUnsigned
+ FixedPointOperand
+ Parameter
+ Parameter
+ Member
+ MaybeSerializeDeserialize
+ Clone
+ Copy
+ Bounded
+ CheckedSub
+ PartialOrd
+ SaturatingAdd
+ Zero
+ TryFrom<sp_core::U256>;
/// Index of a transaction used by the chain.
type Index: Parameter
+ Member
+ MaybeSerialize
+ Debug
+ Default
+ MaybeDisplay
+ MaybeSerializeDeserialize
+ AtLeast32Bit
+ Copy;
/// Signature type, used on this chain.
type Signature: Parameter + Verify;
}
/// Block number used by the chain.
@@ -85,3 +132,21 @@ pub type HasherOf<C> = <C as Chain>::Hasher;
/// Header type used by the chain.
pub type HeaderOf<C> = <C as Chain>::Header;
/// Account id type used by the chain.
pub type AccountIdOf<C> = <C as Chain>::AccountId;
/// Balance type used by the chain.
pub type BalanceOf<C> = <C as Chain>::Balance;
/// Transaction index type used by the chain.
pub type IndexOf<C> = <C as Chain>::Index;
/// Signature type used by the chain.
pub type SignatureOf<C> = <C as Chain>::Signature;
/// Account public type used by the chain.
pub type AccountPublicOf<C> = <SignatureOf<C> as Verify>::Signer;
/// Transaction era used by the chain.
pub type TransactionEraOf<C> = crate::TransactionEra<BlockNumberOf<C>, HashOf<C>>;
+135 -10
View File
@@ -19,11 +19,16 @@
#![cfg_attr(not(feature = "std"), no_std)]
use codec::Encode;
use sp_core::hash::H256;
use frame_support::{RuntimeDebug, StorageHasher};
use sp_core::{hash::H256, storage::StorageKey};
use sp_io::hashing::blake2_256;
use sp_std::convert::TryFrom;
use sp_std::{convert::TryFrom, vec::Vec};
pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
pub use chain::{
AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf,
IndexOf, SignatureOf, TransactionEraOf,
};
pub use frame_support::storage::storage_prefix as storage_value_final_key;
pub use storage_proof::{Error as StorageProofError, StorageProofChecker};
#[cfg(feature = "std")]
@@ -64,19 +69,24 @@ pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/
/// 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";
/// Generic header Id.
#[derive(RuntimeDebug, Default, Clone, Copy, Eq, Hash, PartialEq)]
pub struct HeaderId<Hash, Number>(pub Number, pub Hash);
/// Unique identifier of the chain.
///
/// In addition to its main function (identifying the chain), this type may also be used to
/// identify 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 may be used for that.
/// 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 may be
/// used for that.
pub type ChainId = [u8; 4];
/// Type of accounts on the source chain.
pub enum SourceAccount<T> {
/// An account that belongs to Root (privileged origin).
Root,
/// A non-priviledged account.
/// A non-privileged 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.).
@@ -99,8 +109,10 @@ 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),
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()
}
@@ -109,8 +121,8 @@ where
///
/// 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.
/// 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: ChainId) -> H256 {
("relayer-fund-account", bridge_id).using_encoded(blake2_256).into()
}
@@ -124,6 +136,12 @@ pub trait Size {
fn size_hint(&self) -> u32;
}
impl Size for &[u8] {
fn size_hint(&self) -> u32 {
self.len() as _
}
}
impl Size for () {
fn size_hint(&self) -> u32 {
0
@@ -138,3 +156,110 @@ impl Size for PreComputedSize {
u32::try_from(self.0).unwrap_or(u32::MAX)
}
}
/// Era of specific transaction.
#[derive(RuntimeDebug, Clone, Copy)]
pub enum TransactionEra<BlockNumber, BlockHash> {
/// Transaction is immortal.
Immortal,
/// Transaction is valid for a given number of blocks, starting from given block.
Mortal(HeaderId<BlockHash, BlockNumber>, u32),
}
impl<BlockNumber: Copy + Into<u64>, BlockHash: Copy> TransactionEra<BlockNumber, BlockHash> {
/// Prepare transaction era, based on mortality period and current best block number.
pub fn new(
best_block_id: HeaderId<BlockHash, BlockNumber>,
mortality_period: Option<u32>,
) -> Self {
mortality_period
.map(|mortality_period| TransactionEra::Mortal(best_block_id, mortality_period))
.unwrap_or(TransactionEra::Immortal)
}
/// Create new immortal transaction era.
pub fn immortal() -> Self {
TransactionEra::Immortal
}
/// Returns era that is used by FRAME-based runtimes.
pub fn frame_era(&self) -> sp_runtime::generic::Era {
match *self {
TransactionEra::Immortal => sp_runtime::generic::Era::immortal(),
TransactionEra::Mortal(header_id, period) =>
sp_runtime::generic::Era::mortal(period as _, header_id.0.into()),
}
}
/// Returns header hash that needs to be included in the signature payload.
pub fn signed_payload(&self, genesis_hash: BlockHash) -> BlockHash {
match *self {
TransactionEra::Immortal => genesis_hash,
TransactionEra::Mortal(header_id, _) => header_id.1,
}
}
}
/// This is a copy of the
/// `frame_support::storage::generator::StorageMap::storage_map_final_key` for `Blake2_128Concat`
/// maps.
///
/// We're using it because to call `storage_map_final_key` directly, we need access to the runtime
/// and pallet instance, which (sometimes) is impossible.
pub fn storage_map_final_key_blake2_128concat(
pallet_prefix: &str,
map_name: &str,
key: &[u8],
) -> StorageKey {
storage_map_final_key_identity(
pallet_prefix,
map_name,
&frame_support::Blake2_128Concat::hash(key),
)
}
///
pub fn storage_map_final_key_twox64_concat(
pallet_prefix: &str,
map_name: &str,
key: &[u8],
) -> StorageKey {
storage_map_final_key_identity(pallet_prefix, map_name, &frame_support::Twox64Concat::hash(key))
}
/// This is a copy of the
/// `frame_support::storage::generator::StorageMap::storage_map_final_key` for `Identity` maps.
///
/// We're using it because to call `storage_map_final_key` directly, we need access to the runtime
/// and pallet instance, which (sometimes) is impossible.
pub fn storage_map_final_key_identity(
pallet_prefix: &str,
map_name: &str,
key_hashed: &[u8],
) -> StorageKey {
let pallet_prefix_hashed = frame_support::Twox128::hash(pallet_prefix.as_bytes());
let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes());
let mut final_key = Vec::with_capacity(
pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len(),
);
final_key.extend_from_slice(&pallet_prefix_hashed[..]);
final_key.extend_from_slice(&storage_prefix_hashed[..]);
final_key.extend_from_slice(key_hashed.as_ref());
StorageKey(final_key)
}
/// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false;
/// }`) is computed.
///
/// Copied from `frame_support::parameter_types` macro
pub fn storage_parameter_key(parameter_name: &str) -> StorageKey {
let mut buffer = Vec::with_capacity(1 + parameter_name.len() + 1 + 1);
buffer.push(b':');
buffer.extend_from_slice(parameter_name.as_bytes());
buffer.push(b':');
buffer.push(0);
StorageKey(sp_io::hashing::twox_128(&buffer).to_vec())
}
@@ -23,7 +23,7 @@ use scale_info::TypeInfo;
/// Where message dispatch fee is paid?
#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo)]
pub enum DispatchFeePayment {
/// The dispacth fee is paid at the source chain.
/// The dispatch fee is paid at the source chain.
AtSourceChain,
/// The dispatch fee is paid at the target chain.
///
@@ -51,7 +51,7 @@ pub struct MessageDispatchResult {
/// 2) if message has not been dispatched at all.
pub unspent_weight: Weight,
/// Whether the message dispatch fee has been paid during dispatch. This will be true if your
/// configuration supports pay-dispatch-fee-at-target-chain option and message sender has enabled
/// this option.
/// configuration supports pay-dispatch-fee-at-target-chain option and message sender has
/// enabled this option.
pub dispatch_fee_paid_during_dispatch: bool,
}
@@ -42,7 +42,7 @@ where
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);
return Err(Error::StorageRootMismatch)
}
let checker = StorageProofChecker { root, db };
@@ -52,7 +52,8 @@ where
/// 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)
read_trie_value::<Layout<H>, _>(&self.db, &self.root, key)
.map_err(|_| Error::StorageValueUnavailable)
}
}
@@ -97,7 +98,8 @@ pub mod tests {
let (root, proof) = craft_valid_storage_proof();
// check proof in runtime
let checker = <StorageProofChecker<sp_core::Blake2Hasher>>::new(root, proof.clone()).unwrap();
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));